Documente Academic
Documente Profesional
Documente Cultură
Tehnici de Sortare A Tablourilor
Tehnici de Sortare A Tablourilor
TABLOURILOR
1. Scopul lucrarii:
prezentarea celor mai cunoscute metode de sortare a tablourilor.
2. Aspecte teoretice
In cele ce urmeaza vom presupune ca tablourile de sortat sint definite dupa cum
urmeaza:
TYPE TipElement=RECORD
cheie:Integer;
{alte cimpuri}
END;
TipIndex=1..N;
TipTablou=ARRAY[TipIndex] OF TipElement;
VAR a : TipTablou;
In cazul sortarii prin insertie C si M sint de ordinul N*N, avind valori minime cind
tabloul e ordonat si maxime cind tabloul e ordonat descrescator. Aceasta metoda
este stabila.
2.1.1.b. Sortarea prin insertie binara
Principiu: reprezinta o varianta a sortarii prin insertie, in care cautarea locului de
inserare se face aplicind cautarea binara, stiind ca secventa a[1],...,a[i-1] este deja
ordonata.
Implementarea algoritmului in Pascal:
procedure InsertieBinara;
VAR i,j,s,d,m : TipIndex; x : TipElement;
begin
for i:=2 to N do begin
x:=a[i]; s:=1; d:=i-1;
while s<=d do begin
m:=(s+d) div 2;
if a[m].cheie > x.cheie then d:=m-1
else s:=m+1
end;
for j:=i-1 downto s do a[j+1]:=a[j];
a[s]:=x
end
end; {InsertieBinara}
In cadrul acestei metode, C este de ordinul N*log N, iar M de N*N. Se obtin valori
minime ale lui C pentru tablouri ordonate invers si valori maxime pentru tablouri
ordonate.
2.1.1.c. Sortarea prin selectie
Principiu: se considera subtabloul a[i],...,a[N], se cauta elementul cu cheia minima
din acest subtablou si apoi se interschimba acest element cu elementul a[i],
repetindu-se procedeul pentru valori ale lui i de la 1 la N-1.
Implementarea algoritmului in Pascal:
procedure Selectie;
VAR i,j,k : TipIndex; x : TipElement;
begin
for i:=1 to N-1 do begin
k:=i; x:=a[i];
for j:=i+1 to N do if a[j].cheie < x.cheie then begin
x:=a[j];
k:=j
end;
a[k]:=a[i]; a[i]:=x
end
end; {Selectie}
In cazul sortarii prin selectie C este de ordinul N*N , iar M este de ordinul N*ln N.
Aceasta metoda este mai putin rapida pentru tablouri ordonate sau aproape
ordonate.
2.1.1.d. Sortarea prin selectie performanta
Principiu: reprezinta o varianta a sortarii prin selectie, in care determinarea
elementului cu cheia minima dintr-o portiune de tablou se reduce la determinarea
pozitiei acestuia. Infelul acesta se poate renunta la asignarea x:=a[j] care apare in
ciclul "for" controlat de j.
Implementarea algoritmului in Pascal:
procedure SelectiePerform;
VAR i,j,min : TipIndex; x : TipElement;
begin
for i:=1 to N-1 do begin
min:=i;
for j:=i+1 to N do if a[j].cheie < a[min].cheie
then min:=j;
x:=a[min]; a[min]:=a[i]; a[i]:=x
end
end; {SelectiePerform}
Se aduce tabloul la forma unui ansamblu, adica pentru orice i,j, k din intervalul
[1,N], unde j=2*i si k=2*i+1, sa avem a[i].cheie<=a[j].cheie si
a[i].cheie<=a[k].cheie (*) Se observa ca in acest caz a[1] este elementul cu cheia
minima in tablou. Se interschimba elementele a[1] si a[N] si se aduce subtabloul
a[1],...,a[N-1] la forma de ansamblu, apoi se interschimba elementele a[1] si a[N-1]
si se aduce subtabloul a[1],...,a[N-2] la forma de ansamblu s.a.m.d. In final rezulta
tabloul ordonat invers. Daca se schimba sensul relatiilor in conditiile (*) atunci se
obtine o ordonare directa a tabloului (a[1] va fi elementul cu cheia maxima).
Aducerea unui tablou la forma de ansamblu se bazeaza pe faptul ca subtabloul
a[N/2+1],...,a[N] este deja un ansamblu (nu exista indicii j si k definiti ca mai sus).
Acest subtablou se va extinde mereu spre stinga cu cite un element al tabloului,
pina cind se ajunge la a[1]. Elementul adaugat va fi glisat astfel incit subtabloul
extins sa devina ansamblu.
Implementarea algoritmului in Pascal:
procedure HeapSort;
VAR s,d : TipIndex; x : TipElement;
procedure Deplasare(s,d : TipIndex);
VAR i,j : TipIndex; ret : Boolean;
begin {Deplasare}
i:=s; j:=2*i; x:=a[i]; ret:=False;
while (j <= d) and (not ret) do begin
if j < d then
if a[j].cheie < a[j+1].cheie then j:=j+1;
if x.cheie < a[j].cheie then begin
a[i]:=a[j]; i:=j; j:=2*i
end
else ret:=True
end;
a[i]:=x
end; {Deplasare}
begin {HeapSort}
{constructie ansamblu}
s:=(N div 2) +1; d:=N;
while s > 1 do begin
s:=s-1;
Deplasare(s,N);
end;
{sortare}
while d > 1 do begin
x:=a[1]; a[1]:=a[d]; a[d]:=x;
d:=d-1;
Deplasare(1,d)
end
end; {HeapSort}
In cazul algoritmului nerecursiv este necesara o stiva care memoreaza limitele uneia dintre
cele doua partitii care apar la o trecere, si anume limitele partitiei care este tratata a doua (aici,
partitia dreapta). Timpul de executie este O(N* log N) si O(N*N),in cazul cel mai defavorabil.
Instructiunea marcata cu "*" are ca efect refacerea lungimii partitiei daca toti bitii testati sint
0.
Pentru o distributie normala a bitilor metoda lucreaza mai repede chiar si decit Quicksort.
2.3.b. Sortarea radix directa
Principiu: Examineaza toti bitii care formeaza cheia de la dreapta la stinga, considerind cite
"m" biti deodata (unde "m" este un divizor al lungimii cheii - "b"). In felul acesta sortarea se
executa in b/m treceri. Aplicarea acestei metode de sortare presupune folosirea unui tablou
auxiliar T care memoreaza rezultatul fiecarei treceri, precum si a unui tablou Numar care sa
contina distributia cheilor in raport cu cei "m" biti considerati la un moment dat: adica pentru
fiecare combinatie posibila de "m" biti trebuie sa se determine numarul cheilor care contin
acea combinatie; de aici rezulta ca dimensiunea tabloului Numar este 2**m. Pentru ca
algoritmul sa functioneze corect este necesar ca fiecare sortare dupa "m" biti sa fie stabila.
Se observa ca numarul de treceri se reduce daca "m" este mare, ceea ce conduce insa la
cresterea dimensiunii tabloului Numar. S-a constatat ca metoda este eficienta pentru m=4 sau
m=8.
Implementarea algoritmului in Pascal:
procedure RadixDirect;
VAR i:TipIndex;
j,k:0..M1;
{M1 = 2**m-1}
Trecere:Integer;
Numar:ARRAY[0..M1] OF Integer;
T:TipTablou;
begin
for Trecere:=0 to (b div m)-1 do begin
for j:=0 to M1 do Numar[j]:=0;
for i:=1 to N do begin
k:=Biti(a[i].cheie,Trecere*m,m);
Numar[k]:=Numar[k]+1;
end;
for j:=1 to M1 do {*}
Numar[j]:=Numar[j-1]+Numar[j];
for i:=N downto 1 do begin {**}
k:=Biti(a[i].cheie,Trecere*m,m);
T[Numar[k]]:=a[i];
Numar[k]:=Numar[k]-1;
end;
for i:=1 to N do a[i]:=T[i];
end;
end; {RadixDirect}
Observatii: in ciclul "for" notat cu "*" se determina practic indicii in tabloul T la care vor fi
plasate elementele tabloului a la fiecare trecere; in ciclul "for" notat cu "**" tabloul a este
parcurs de la sfirsit spre inceput pentru a se respecta necesitatea ca sortarea dupa "m" biti sa
fie stabila.