Documente Academic
Documente Profesional
Documente Cultură
Sortări
Nota teoretica:
a) instabila 4734334
3334447
b) stabila 4734334
3334447
Fig1. Stabilitate – fiecare element isi mentine pozitia (culoarea) respectiv inregistrarile cu
chei egale isi pastreaza pozitiile relative in urma sortarii
Testarea sortarii
Cateva extreme:
1) Bogosort (goro, bozo, etc)
2) Quick Sort
Este sortare prin comparaţie, varianta de bază este stabilă şi necesită consum suplimentar
de memorie.
procedure quick_sort(array)
list left, right
if (length(array)<2) return array
pivot = last(array)
remove(last(array))
foreach x in array
if (x<=pivot) append(left, x)
else append(right, x)
return concatenate(quick_sort(left), pivot, quick_sort(right))
Procedură recursivă!
2. Impera: cele două părţi sunt sortate apelând recursiv până când se ajunge la porţiuni
formate dintr-un singur element.
3. Combină: având în vedere că fiecare subvector este sortat şi cel mai mare element din
subvectorul din stânga este mai mic sau egal decât cel mai mic element din subvectorul
din dreapta atunci întregul vector este de fapt sortat.
Implementarea algoritmului:
Procedura de partiţionare. Există mai multe moduri în care putem împărţi vectorul, dar
următorul algoritm, inventat, de R. Sedgevvick, pare a fi cel mai bun: se porneşte de la
ambele capete, folosind doi indicatori, i pentru partea stângă, j pentru partea din dreapta,
căutându-se elementele care ar trebui să fie în cealaltă parte; în momentul în care se
găsesc elementele se verifică dacă i < j; dacă da se interschimbă cele două elemente şi se
continuă algoritmul, altfel algoritmul întoarce valoarea lui j; element de referinţă se
consideră ca fiind primul element din vector.
Descrierea algoritmului:
Descrierea algoritmului in C:
Dacă v[i] este mai mic decât elementul de referinţă atunci cu certitudine el face parte din
primul subvector, altfel, este un element care poate fi plasat în cel de-al doilea subvector.
Primul ciclu caută elemente mai mari sau egale cu elementul de referinţă.
Dacă v[j] este mai mare decât elementul de referinţă atunci cu certitudine el face parte
din cel de-al doilea subvector, altfel, este un element care poate fi plasat în primul
subvector. Cel de-al doilea ciclu caută elemente mai mici sau egale cu elementul de
referinţă.
Primul lucru pe care trebuie să-1 demonstrăm este că cele două cicluri se termină. Prima
valoare a lui i pentru care se termină primul ciclu este chiar st deoarece acesta este
elementul de referinţă. Avem mai multe cazuri:
Cazul 1: x este cel mai mic element din vector, ne mai existând nici un element egal cu
el.
In cazul în care x este cel mai mic element din vector, neexistând nici un element egal
cu.el, cel de-al doilea ciclu se termină tot cu j egal cu st. In acest caz partiţionarea se
încheie, cel mai din dreapta element al subvectorului stâng fiind cel de pe poziţia j.
Cazul II: Există cel puţin un element mai mic sau egal cu x.
In acest caz, cel de-al doilea ciclu se termină pe primul element mai mic sau egal decât x.
Deoarece acest element se află în dreapta primului element are loc interschimbarea celor
două elemente. Să presupunem acum că ultima interschimbare pe care o efectuează
algoritmul este cea dintre elementele v[p] şi v[q], cu p <q. După interschimbare avem
v[p] <= x şi x <= v[q]. Acum avem două subcazuri:
a) q - p = 1. In acest caz cele două elemente au fost şi au rămas vecine. Cele două cicluri
se încheie cu i = q şi j = p. Este evident că algoritmul se încheie întorcând indexul celui
mai din dreapta element ai subvectorului stâng, adică valoarea lui j.
b) q - p > 1. Este evident că cele două cicluri se încheie, în cel mai rău caz când primul
ciclu îl va găsi pe v[q], iar cel de-al doilea ciclu îl va găsi pe v[p]. Deoarece nu se mai
efectuează nici o interschimbare, cele două cicluri se încheie cu i >= j. Avem v[k] < x,
pentru oricare k din intervalul [p + 1, i - 1] şi x < v[m] pentru oricare m din intervalul
[j+1, q-1]. Este evident că cele două intervale, [p + 1, i - 1] şi [j+1, q-1], sunt disjuncte.
Avem deci i - 1 < j + 1, de unde rezultă că i - j < 2.
In cel mai rău caz, partiţionarea produce o regiune cu un singur element. Cel mai bun caz
se obţine atunci când vectorul este împărţit în două părţi egale. Timpul mediu este mai
apropiat de cel mai bun caz, adâncimea arborelui de partiţionare fiind aproximativ egală
cu log2n, iar pentru fiecare nivel sunt comparate toate elementele arborelui cu elementele
de referinţă, ceea ce înseamnă că avem o complexitate de ordinul n. Deci complexitatea
algoritmului este de ordinul n*log2n, notată cu
O(n*log2n). în cel mai rău caz, care se obţine de exemplu atunci când şirul este deja
sortat, adâncimea arborelui este n, ceea ce ne duce la complexitatea 0(n2). Pentru a evita
obţinerea celui mai rău caz se poate modifica procedura de partiţionare astfel încât
elementul de referinţă să fie ales aleator.
T(0) = T(1) = 0
T(n + 1) = T(n) + T(0) + n = T(n) + n, n>0
for i=0 to n-2 // fixez cate un pivot si numar toate elem a caror val e
mai mare, adaugand cate un 1 dupa caz
for j=i+1 to n-1 do
if a[i]<a[j] then
B[j]++
else
B[i]++
6) sortarea radix
Radix sort
Imagine din:
procedure insertion_sort(array)
for i = 2 to n // 1 to n-1
key = array[i]
j=i-1
while (j ≥ 1 and array[j] > key)
do array[j + 1] = array[j]
j=j−1
array[j + 1] = key
exemplu:
A= (2, 5, 1, 7, 2)
*****
i=2;
key=5;
j=1;
A[2]=5;// (2/>5)
---
i=3;
key=1;
j=2; //(5>2);
A[3]=5; //A=(2, 5, 5, 7, 2);
j=1;
A[2]=1; // A= (2, 1, 5, 7, 2); j>=1;A[1]=2>1
A[2]=A[1]; // A= (2, 2, 5, 7, 2); j=0
A[1]=1; // A = (1, 2, 5, 7, 2)
--------
i=4
key=7 ....
-----
i=5
key=2
j=4... A=(1, 2, 5, 7, 7), A= (1, 2, 5, 2, 7), A= (1, 2, 5, 5, 7), A= (1, 2, 2, 5, 7)
Analiza complexităţii
1. Cazul cel mai nefavorabil: lista este sortată descrescător.
Se compară fiecare element cu toate cele care îl preced, inclusiv:
n 1
n(n 1)
T (n) 1 2 ... n 1 i O(n 2 )
i 1 2
7 6 5 4 3 2 1
7 6 5 4 3 2 1
2. Cazul mediu:
O(n^2)