Sunteți pe pagina 1din 46

Algoritmi, Structuri de date şi

Complexitate

Tema: Tehnici de sortare.


Aprecierea complexităţii

Ludmila NOVAC
Dr., conf. univ.
Dep. Informatică
Unităţi de conţinut
1. Tehnici de sortare. Noţiunea de sortare şi tipuri de sortare.
Sortarea bazată pe comparaţii, aprecierea algoritmilor de
sortare. Algoritmi de sortare prin interschimbare. Metoda
bulelor, sortarea bazată pe metoda „Divide et Impera”
(sortare rapidă - quicksort). Aprecierea complexităţii.
Îmbunătăţirile algoritmului de sortare rapidă.
2. Algoritmi de sortare prin inserţie. Inserţia simplă
recursivă, inserţia simplă iterativă. Sortarea prin metoda lui
Shell. Algoritmi de sortare prin interclasare (mergesort).
Aprecierea complexităţii.
3. Algoritmi de sortare prin selecţie. Selecţia simplă. Selecţia
sistematică (piramidală, arborescentă - heapsort). Aprecierea
complexităţii.
Tehnici de sortare şi
Algoritmi de sortare
• Metoda bulelor de sortare (Bubble Sort)
• Metoda de sortare prin inserţie (Insertion Sort)
• Metoda de sortare prin selecţie (Selection Sort)
• Metoda rapidă de sortare (Quick Sort)
• Metoda Shell de sortare (Shell Sort)
• Metoda Heap (piramidală, arborescentă) de
sortare (Heap Sort)
• Metoda de sortare prin interclasare (mergesort).
Problema sortării
• Fie şirul: x[1], x[2], … , x[n].
• Dacă notăm cheia elementului xi cu Ki, atunci sortarea şirului presupune
determinarea unei permutări
p(1), p(2), … , p(n)
astfel încât: Kp(1) ≤ Kp(2) ≤ … ≤ Kp(n).
• Pentru simplitate, considerăm că cheia de sortare Ki este reprezentată de întregul
element xi.
• Fie un şir de “entităţi”: numere, caractere, înregistrări ale unei baze de
date, etc. Fiecare entitate deţine o caracteristică numită cheie de sortare.
• Există o relaţie de ordine ce se defineşte peste mulţimea valorilor posibile
ale cheii de sortare.
• Sortarea şirului = dispunerea elementelor şirului astfel încât valorile cheilor
de sortare să se afle în ordine crescătoare (sau descrescătoare)
Clasificarea algoritmilor de sortare (1)
Putem clasifica algoritmii de sortare după o serie de criterii. Cei mai cunoscuţi
algoritmi sunt cei prin comparaţie, iar cel mai comun criteriu de clasificare a
acestora este după metoda generală de lucru.
Astfel avem algoritmi de sortare prin:
Inserţie:
• Insertion sort – un algoritm de sortare eficient pe liste de intrare mici sau
aproape sortate,
• Shellsort,
• Binary tree sort,
• Cyclesort – un algoritm cu numărul de scrieri în memorie redus
Selecţie:
• Selectionsort – eficient pe liste de intrare mici
• Heapsort – un algoritm de sortare cu timp de execuţie constant
• Smoothsort – inspirat de Heapsort, dezvoltat de către Edsger Dijkstra
Algoritmii de sortare prin inserţie şi selecţie sunt în general algoritmi care nu
pot fi uşor paralelizaţi, dar pot fi folosiţi împreună cu alţi algoritmi pentru a
forma algoritmi de sortare hibrizi. Mai avem algoritmi de sortare prin:
Partiţionare:
• Quicksort – unul dintre cei mai cunoscuţi algoritmi de sortare
• Introsort – un hibrid între Quicksort şi Heapsort.
Clasificarea algoritmilor de sortare (2)
Interclasare (merging):
• Mergesort
• Timsort – este un hibrid între Mergesort şi Insertion sort
Distribuire:
• Bucketsort

Algoritmii prin partiţionare, interclasare şi distribuire sunt algoritmii care


pot fi paralelizaţi cel mai uşor datorită naturii acestora.
Printre cei mai lenţi algoritmi se numără cei prin inter-schimbare:
• Bubblesort
• Odd-even sort - o variaţie uşor îmbunătăţită a Bubble-sort
Toţi algoritmii prezentaţi anterior fac parte din categoria algoritmilor de
sortare prin comparaţie.
Exemple de algoritmi de sortare care nu folosesc comparaţia sunt:
• Radix sort
• Bead sort
Funcţii uzuale de complexitate
Tehnici de sortare şi
Algoritmi de sortare
• Metoda bulelor de sortare (Bubble Sort)
• Metoda de sortare prin inserţie (Insertion Sort)
• Metoda de sortare prin selecţie (Selection Sort)
• Metoda rapidă de sortare (Quick Sort)
• Metoda Shell de sortare (Shell Sort)
• Metoda Heap (piramidală, arborescentă) de
sortare (Heap Sort)
• Metoda de sortare prin interclasare (mergesort).
Metoda bulelor de sortare (Bubble Sort)
Descrierea metodei
• Idei generale:
• Considerăm şirul: x[1], x[2], … , x[n].
• Se parcurge secvenţial şirul (element cu element). Se compară elementul
curent cu următorul şi, în cazul în care se află în ordinea nepotrivită, se
interschimbă elementele.
• Se efectuează parcurgeri până şirul nu mai necesită interschimbări

BubbleSort nu foloseşte alte structuri de date şi din această cauză este


recomandabil în cazurile cu puţine elemente de sortat şi în cazul în care
memoria este limitată.
Metoda bulelor de sortare (Bubble Sort)
Analiza complexităţii
• Acesta metoda se rezumă la a compara fiecare element cu celelalte,
făcându-se interschimbarea dacă elementul mai mare are indexul mai mic.
Este cea mai simpla metode de sortare şi nu necesită cunoaşterea detaliată
a limbajului de programare. Poate fi folosită cu succes de către începători.

• Bubble sort este o metodă de sortare simplă, eficientă pentru un număr mic
de elemente (mai puţin de 15), dar nu pentru tabele mari.
• Metoda Bulelor nu necesită foarte multă memorie,
dar este de două ori mai lentă decât InsertionSort în aproape
orice situaţie.
• Timpul de execuţie depinde de input, adică de ordinea iniţială a elementelor.
• Dacă tabela este deja sortată e nevoie de un singur pas, adică
N-1 comparări. În cazul cel mai nefavorabil sunt necesare
N×(N-1)/2 comparări şi N×(N-1)/2 interschimbări.
• Performanţa algoritmului în caz general este mai greu de analizat dar este
asemănător cazului nefavorabil. Complexitatea timpului al Bubble sortului
este .
Metoda bulelor de sortare (Bubble Sort)
Pseudocod

Algoritm Sort-Interschimbare(array x):

repeat
for i = 2 … n
if (x[i] < x[i − 1]) // dacă x[i] şi x[i − 1] nu sunt ordonate
x[i − 1] ↔ x[i] // se interschimbă x[i] cu x[i − 1]
swap =true
endif
endfor
until not swap // repetă până nu mai sunt necesare interschimbări
return x
Metoda bulelor de sortare (Bubble Sort).
Exemplu
Metoda bulelor de sortare (Bubble Sort)
Analiza complexităţii
Metoda bulelor de sortare (Bubble Sort)
Analiza complexităţii
Metoda bulelor de sortare (Bubble Sort)
Analiza complexităţii
Metoda de sortare prin interclasare (Mergesort)
Algoritmul de sortare prin interclasare se bazează pe următoarea idee: pentru a
sorta un tabel cu N elemente îl împărţim în două tabele pe care le sortăm separat şi le
interclasăm. Este o metodă de sortare care foloseşte strategia de bază "divide et impera",
conform căreia problema se descompune în alte două subprobleme de acelaşi tip şi după
rezolvarea lor rezultatele se combină. Algoritmul sortează elementele în ordine crescătoare.
Tabelul se împarte in n/2, după aceea tabelele se împart în jumătate, tot aşa până când tabelele
formate au mai puţin sau cel mult de k elemente (în cazul nostru k=2-este cel mai uşor să comparăm
2 elemente).
Metoda de sortare prin interclasare
(Mergesort)
Metoda de sortare prin interclasare
(Mergesort)
Metoda de sortare prin interclasare (Mergesort)
Exemplul
Algoritmul de sortare prin interclasare
Sortare prin interclasare - Eficienţă
Sortare prin interclasare - Eficienţă
Metoda rapidă de sortare (Quick Sort)
Formularea Algoritmului:

• Algoritm de sortare eficient dezvoltat de Tony Hoare în 1959 şi publicat în 1961.


• Implementările bune pot depăşi de 2-3 ori performanţele sortării prin interclasare
(Mergesort).
Idei generale:
• Considerăm şirul: x[1], x[2], … , x[n].
• Se alege din şir un element, numit pivot.

• Se realizează partiţionarea şirului (în raport cu acest pivot): se reordonează


şirul astfel încât elementele cu valori mai mici decât pivotul se plasează
înainte de pivot (la stânga lui), iar elementele cu valori mai mari decât pivotul
se plasează după acesta (la dreapta lui), (cele egale cu el în oricare din
parţi).
• După partiţionare, pivotul se află in poziţia finală. Se aplică recursiv aceeaşi
procedură subşirului de elemente cu valori mai mici, iar separat subşirului cu
valori mai mari. În final întreg şirul va fi sortat crescător.
Alegerea pivotului şi partiţionarea

• Ca şi la MergeSort, QuickSort este un algoritm din categoria Divide


and Conquer. Selectează un element în calitate de pivot şi împarte
tabloul de valori în jurul pivotului selectat.

• Există mai multe versiuni diferite ale QuickSort care aleg pivotul în
diferite moduri:
1. Alegerea primului element ca pivot (întotdeauna),
2. Alegerea ultimului element ca pivot (întotdeauna), (implementat mai
jos)
3. Alegerea unui element aleatoriu ca pivot.
4. Alegerea medianei ca pivot.

• Procesul cheie în QuickSort este partiţia(). Obiectivul partiţiilor este de


a repartiza elementele vectorului de intrare la stânga sau la dreapta
elementului pivot. Toate acestea trebuie făcute în timp liniar.
Metoda rapidă de sortare (Quick Sort)
• În practică algoritmul de sortare cel mai rapid este Quicksort numită sortare rapidă, care
foloseşte partiţionarea ca idee de bază.

• Este mai rapidă decât orice metodă de sortare simplă, se execută bine pentru fişiere sau tabele
mari, dar ineficient pentru cele mici.
• Strategia de bază folosită este "divide et impera", pentru că este mai uşor de sortat două tabele
mici, decât una mare.
• Algoritmul este uşor de implementat, lucrează destul de bine în diferite situaţii şi consumă mai
puţine resurse decât orice altă metodă de sortare în multe situaţii.
• Necesită numai în jur de NlogN operaţii în cazul general pentru a sorta N elemente.

• Metoda QuickSort presupune găsirea poziţiei finale pe care o ocupă elementul de


pe prima poziţie comparându-l cu elementele din cealaltă partiţie a tabelului,
acest algoritm realizându-se până când partiţia are 1 element.

Potrivit algoritmului, fiecare element este comparat cu pivotul, adică operaţiunea este
de O(N), tabela este divizată în două părţi, fiecare parte este divizată iarăşi în două.
Dacă fiecare parte este împărţită aproximativ în jumătate, va rezulta log2N împărţiri.
Deci timpul de execuţie al Quicksortului în caz mediu este de O(N log2 N), iar în caz
nefavorabil O(N2).
Quicksort este o metodă bună în caz general, dar nu şi în caz nefavorabil când este
preferabil folosirea a 3 indicii de împărţire. Randomizarea este o idee importantă şi folositoare, o
unealtă generală pentru a îmbunătăţi algoritmul. Quicksort este sensibil la ordinea datelor de
intrare. Nu este o metodă stabilă.
Dezavantajul algoritmului este că, e recursiv. Necesită în jur de N 2 de operaţii în caz
nefavorabil. Este fragil, o simplă greşeală în implementare poate cauza o executare greşită pentru
anumite fişiere.
• https://sortari.weebly.com/
Metoda rapidă de sortare (Quick Sort)
Pseudocod:
/* low --> Starting index, high --> Ending index */
quickSort(arr[ ], low, high)
{
if (low < high)
{
/* pi is partitioning index, arr[pi] is now at right place */
pi = partition(arr, low, high);
quickSort(arr, low, pi - 1); // Before pi
quickSort(arr, pi + 1, high); // After pi
}
}

/* Această funcţie ia ultimul element ca pivot, aşează elementul pivot în poziţia sa


corectă în vectorul sortat şi plasează toate elementele mai mici decât pivotul spre
stânga pivotului şi toate elementele mai mari la dreapta pivotului */
Pseudo code pentru partition()
Metoda rapidă de sortare (Quick Sort)
Exemple
Metoda rapidă de sortare (Quick Sort)
Exemplul 2

https://en.wikipedia.org/wiki/Quicksort
Metoda rapidă de sortare (Quick Sort)
Exemple
Exemplul 3 Exemplul 4
• 634 5123
• 3 1 2 |3| 6 4 5
• 1 2 3 |3| 4 5 6

• 1 2 3 |3| 4 5 6
• 123 3456
Metoda rapidă de sortare (Quick Sort)
Eficienţa
Metoda Shell de sortare (Shell Sort)
• Algoritmul shell sort este o generalizare a algoritmului insertion sort.
La algoritmul insertion sort, pentru a insera un nou element în lista de
elemente deja sortate, se deplasează fiecare element cu câte o poziţie spre
dreapta atât timp cât avem elemente mai mari decât el. Practic fiecare
element înaintează spre poziţia sa finală cu câte o poziţie.

• Algoritmul shell sort lucrează similar, doar că deplasează elementele spre


poziţia finală cu mai mult de o poziţie. Se lucrează în iteraţii. În prima iteraţie
se aplică un insertion sort cu salt s1 (=N/2) mai mare decât 1. Asta
înseamnă că fiecare element din şirul iniţial este deplasat spre stânga cu
câte s1 poziţii atât timp cât întâlneşte elemente mai mari decât el.
• În a doua iteraţie se aplică un insertion sort cu un salt s2 (= s1 /2) , mai mic
decât s1 şi mai mare decât 1. Din nou fiecare element din şir este deplasat
spre stânga cu câte s2 poziţii, atât timp cât întâlneşte elemente mai mari
decât el.
• Se repetă asemenea iteraţii cu salturi din ce în ce mai mici, s3, s4, etc.
Ultima iteraţie se face cu saltul 1. Această ultimă iteraţie este practic
un insertion sort clasic.

• Principiul este că după fiecare iteraţie şirul devine din ce în ce “mai sortat”.
Iar cum algoritmul insertion sort funcţionează cu atât mai repede cu cât şirul
este mai sortat, per ansamblu vom obţine o îmbunătăţire de viteză.
http://staff.cs.upt.ro/~gabia/TP/2008/L13-Sortari.htm
Metoda Shell de sortare (Shell Sort)
Metoda Shell de sortare (Shell Sort)
Metoda Shell de sortare (Shell Sort)
Metoda Shell de sortare (Shell Sort)
Exemplu
32 95 16 82 24 66 35 19 75 54 40 43 93 68 --: Prima iteraţie se face cu salt 5.
32 35 16 82 24 66 95 19 75 54 50 43 93 68
32 35 16 75 24 66 95 19 82 54 50 43 93 68
32 35 16 75 24 50 95 19 82 54 66 43 93 68
32 35 16 75 24 50 43 19 82 54 66 95 93 68

32 35 16 68 24 50 43 19 75 54 66 95 93 82 Cu asta se încheie prima iteraţie, de salt


5. Putem observa că deja şirul este “mai sortat” decât a fost iniţial. Se poate continua cu
o iteraţie de salt 3 şi pe urmă cu una de salt 1, în urma căruia şirul va fi deplin sortat.

32 24 16 68 35 50 43 19 75 54 66 95 93 82
32 24 16 43 35 50 68 19 75 54 66 95 93 82
32 24 16 43 19 50 68 35 75 54 66 95 93 82
32 24 16 43 19 50 54 35 75 68 66 95 93 82 ….

http://staff.cs.upt.ro/~gabia/TP/2008/L13-Sortari.htm
Metoda Shell de sortare (Shell Sort)
Exemplu

https://www.tutorialspoint.com/data_structures_algorithms/shell_sort_algorithm.htm
Metoda Shell de sortare (Shell Sort)
Analiza complexităţii.

Cazul mediu : -
Cazul defavorabil : O(N * log^2 N)
Memorie folosita : O(1)
Stabilitate : NU
Sortare descrescatoare : j >= h && a[j-h] < v
Sortare crescatoare : j >= h && a[j-h] > v
Întrebări frecvente

• Ce este complexitatea unui algoritm?


• Care algoritm de sortare este cel mai bun şi de ce?
• Care este cel mai lent algoritm de sortare?
• Care este cel mai rapid algoritm de sortare?
• Care este complexitatea celui mai rău caz?
…… etc.
Time Complexity / Space complexity

http://anandabhisheksingh.me/sorting-algorithm/
Aprecierea algoritmilor de sortare

https://www.infopulse.com/blog/timsort-sorting-algorithm/
Aprecierea algoritmilor de sortare

42
Compararea Algoritmilor de sortare
Compararea Algoritmilor de sortare
Concluzii

• O mulţime de metode de sortare bazate pe comparaţii între chei, cu


avantaje şi dezavantaje proprii

• Aplicaţia practică dictează alegerea metodei

• Metodele de sortare prin inserţie şi selecţie au performanţe bune


când şirul de sortat are dimensiuni reduse

• Pentru şiruri de dimensiuni mari: sortare prin interclasare


(Mergesort), sortare rapidă (Quicksort), etc.
Lucrarea de laborator nr.2
„ Metode de sortare”
Termen 3 săptămâni
Să se creeze un fişier textual care conţine cel puţin 50 de înregistrări, cu cel puţin 5 câmpuri
şi are cel puţin 2 tipuri de date, iar câmpul cheie trebuie să fie unic şi neordonat.
Fişierul creat este cel de la prima lucrare de laborator.
Să fie realizat un program în C++, în care sunt implementate câteva metode de sortare (cel
puţin două) în tabele neordonate după câmpul cheie din fişierul textual creat anterior.
Pentru fiecare metodă de sortare de analizat complexitatea teoretică şi practică.
Să se afişeze următoarele date:
Estimarea teoretică a complexităţii; Număr de comparaţii; Număr de
permutări; Timpul de execuţie al fiecărui algoritm de sortare.
De descris algoritmul metodelor de căutare pe paşi.
+ Metoda bulelor (Bubble Sort)
+ Metoda de inserţie (Insertion Sort)
+ Metoda de selecţie (Selection Sort)
+ Metoda rapidă de sortare (Quick Sort)
+ Metoda Shell de sortare (Shell Sort)
+ Metoda Heap (piramidală, arborescentă) de sortare (Heap Sort)

?? Metoda de sortare prin interclasare (mergesort).

S-ar putea să vă placă și