Sunteți pe pagina 1din 47

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 interschimbare (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).
Problema sortării. Noţiuni generale.
• Sortarea este operaţia de aranjare a elementelor unui vector după valoarea
cheilor, pentru care este definită relaţia de ordine.
• Tradiţional, sortarea internă se deosebeşte de sortarea externă.
• Sortarea internă prelucrează datele păstrate în memoria operativă a
calculatorului (ex. tablourile unu-dimensionale sau multidimensionale şi
accesul arbitrar la elementele lor), dar sortarea externă, operează cu datele
care sunt păstrate în fişiere.

• În cazul sortării interne se tinde la minimizarea numărului de comparaţii şi


permutări ale elementelor. Datele se ordonează de obicei în acelaşi loc fără
consum suplimentar de memorie (în cazul calculatoarelor moderne se
utilizează cu succes paginarea memoriei şi utilizarea memoriei cash).
• În cazul sortării externe factorul hotărâtor este numărul de operaţii de intrare
şi ieşire. În acest caz numărul de comparaţii trece pe planul doi, totuşi şi el
se ia în consideraţie. Sortarea externă operează cu dispozitive de stocare
pe scară largă, dar nu cu acces aleatoriu, ci secvenţială (ordonarea
fişierelor), adică un singur element este “vizibil” la un moment dat, iar
cheltuielile de rulare sunt nejustificat de mari comparativ cu memoria
utilizată. Acest lucru impune anumite restricţii suplimentare asupra
algoritmului și duce la metode speciale de sortare, de obicei utilizând spaţiu
pe disc suplimentar. În plus, accesul la date în memoria externă este mult
mai lent decât operaţiile cu memoria RAM.
Clasificarea algoritmilor de sortare

• De asemenea, algoritmii sunt clasificaţi după:

• necesitatea de memorie suplimentară sau absenţa


acestei necesităţi.
• necesitatea de cunoaştere a structurii datelor dincolo
de sfera operaţiei de comparaţie sau lipsa acesteia.
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.
Problema sortării
• Fie un şir de “entităţi”: e.g. 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)
Problema sortării - Exemple

• Elemente numerice: [1, 5, 2, 3, 6, 10, 22, 4, 44]. În acest caz cheia


de sortare este reprezentată de însuşi elementul şirului.
• Elemente definite de înregistrări cu mai multe câmpuri (nume şi
vârstă):
(Andrei, 29), (Paul, 29), (Tiberiu, 10), (Corina, 25), (Claudiu, 19).
Două posibile chei de sortare pentru fiecare element:
– Nume
– Vârstă
Sortare după nume:
(Andrei, 29), (Claudiu, 19), (Corina, 25), (Paul, 29), (Tiberiu, 10).
Sortare după vârstă:
(Tiberiu, 10), (Claudiu, 19), (Corina, 25), (Andrei, 29), (Paul, 29).
Proprietăţi ale metodelor de sortare
1. Eficienţa. Orice metodă de sortare este caracterizată de volumul de resurse
(timp de execuţie) necesitat pentru rezolvarea problemei.
– Număr de comparaţii (de chei),
– Număr de deplasări (de date).
2. Stabilitate. O metodă de sortare este stabilă dacă ordinea relativă a
elementelor cu aceeaşi cheie de sortare rămâne neschimbată.
Aranjament iniţial:
(Andrei, 29), (Paul, 29), (Tiberiu, 10), (Corina, 25), (Claudiu, 19).
Sortare stabilă:
(Tiberiu, 10), (Claudiu, 19), (Corina, 25), (Andrei, 29), (Paul, 29).
Sortare instabilă:
(Tiberiu, 10), (Claudiu, 19), (Corina, 25), (Paul, 29), (Andrei, 29).
3. Simplitate. O metodă de sortare este caracterizată de nivelul de complexitate
al implementării sale în practică.
4. Utilizarea operaţiei de comparare. Algoritmii care utilizează compararea
elementelor între ele pentru sortare sunt numiţi algoritmi bazaţi pe
comparaţii. Complexitatea minimă a celui mai rău caz pentru aceşti
algoritmi este ( ), dar ei diferă în ceea ce priveşte flexibilitatea aplicaţiei.
5. Comportamentul firesc este eficacitatea metodei atunci când se prelucrează
datele deja sortate sau parţial sortate. Algoritmul se comportă în mod
natural dacă ia în considerare această caracteristică a secvenţei de intrare
şi funcţionează mai bine.
Cazul sortării interne
• Presupunem, că datele supuse sortării se păstrează în memoria operativă într-un
vector t. Fiecare element t[i] al acestui vector este obiect al clasei parametrizate în
care sunt supraîncărcaţi operatorii de comparaţie. Deci, sunt admise expresii:
t[i]<t[j], t[i]<=t[j], etc. Vom folosi următoarele noţiuni:

• Definiţia 1. Perechea de indici (i,j), astfel ca i<j, dar t[i]>t[j] se numeşte


inversie.
• Definiţia 2. Vectorul t se numeşte sortat în ordine crescătoare, dacă el nu conţine nici o
inversie.
• Definiţia 3. Vectorul t se numeşte sortat în ordine descrescătoare, dacă pentru orice i, j,
i<j rezultă că sau (i,j) este inversie, sau t[i]==t[j].
• Definiţia 4. Algoritmul sortării se numeşte stabil, dacă el niciodată nu schimbă ordinea
relativă în vector la oricare 2 elemente cu cheile egale. Adică pentru orice pereche i, j:
i<j; t[i]=t[j], i—>i', j—>j' => i'<j'.

Stabilitatea poate fi o cerinţă definitoare, de exemplu când are loc sortarea după o anumită
cheie a elementelor deja sortate după o altă cheie.
Exemplu: lista studenţilor care este deja sortată după numele se cere de aranjat după anul
de studii, dar pentru fiecare an de studii numele trebuie să rămână în ordinea alfabetică.
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
Algoritmi şi complexitate
• Enunţ
• Algoritmi de rezolvare
– Care algoritm este mai bun?
• Datele de intrare
– Forma datelor de intrare influenţează performanţele unui algoritm
• Implementare
• Cum evaluăm un algoritm?
– Timp de execuţie. Timpul depinde de maşina pe care rulează
programul. Ne trebuie o metodă de evaluare care să nu depindă
de maşină => Complexitate timp
– Spaţiu de execuţie. De foarte multe ori la fel de important ca
timpul de execuţie şi în strânsă legătură cu acesta =>
Complexitate spaţiu
Evaluarea algoritmului de sortare
Algoritmii de sortare sunt estimate prin viteza de execuție și eficiența utilizării
memoriei:
• Timpul de execuţie este parametrul principal care caracterizează viteza algoritmului.
Se mai numeşte şi complexitate computaţională. Pentru sortare sunt importante cel
mai bun caz, cel mai rău caz şi cazul mediu al comportamentului algoritmului în ceea
ce priveşte puterea setului de intrare A.
Dacă la intrare algoritmului i se atribuie o mulţime A, atunci considerăm n = |A|. Pentru
un algoritm tipic, comportamentul bun este O(n log n), iar comportamentul rău este
O(n2). Comportamentul ideal pentru un algoritm de sortare este O(n).
Algoritmii de sortare care utilizează doar operaţia abstractă de comparaţie a cheilor
necesită întotdeauna cel puţin O(n log n) comparaţii. Există şi noţiunea de reţele de
sortare. Se admite că se pot efectua mai multe comparaţii simultan (de exemplu, în
calculul paralel), se pot sorta n numere prin O(log2 n) operaţii. În acest caz, numărul
de elemente n trebuie să fie cunoscut în prealabil.

• Memorie – unii algoritmi necesită alocarea de memorie suplimentară pentru stocarea


temporară a datelor. De regulă, aceşti algoritmi necesită O(n log n) memorie.
Estimarea nu ia în considerare spaţiul ocupat deja de tabloul iniţial şi care nu depind
de consumul de memorie pentru secvenţa de intrare.
Despre complexitatea algoritmilor de sortare
• La caracterizarea algoritmilor de sortare se foloseşte noţiunea de mărime (de
exemplu numărul de comparaţii de chei) care depinde de un număr natural n (de
exemplu numărul de elemente) relativ la o altă mărime cunoscută care tot depinde de
acest număr natural. Se spune că mărimea k are ordinul comparabil cu mărimea m,
se notează k=O(m), dacă:

• Din formula aceasta rezultă că mărimile n-1, n, 2n, n+3 au unul şi acelaşi ordin O(n).
Iar mărimea n2 are un ordin mai mare.
• Algoritmul de sortare a n elementele bazat pe compararea cheilor are complexitatea
minimă O(n) sau mai mare.

• Demonstrăm prin inducţia matematică:


Pentru k = 2 – o comparaţie. Presupunem că pentru k = n-1 trebuiesc n-2 comparaţii.
Se adaugă încă un element, deci mai trebuie de făcut cel puţin încă o comparaţie,
obţinem n-2+1 = n-1 comparaţii. Deci, complexitatea minimă este O(n).
• Teoretic este demonstrat că complexitatea medie a oricărui algoritm de sortare care
operează cu comparaţiile nu poate fi mai mică de O(n log2n).
• Algoritmii triviali de sortare bazaţi pe compararea cheilor au complexitatea atât medie
cât şi cea maximă .
• Complexitatea medie a oricărui algoritm bun de sortare bazat pe compararea cheilor
este O(nlog2n), totodată complexitatea maximă a lui poate fi ori O(n log2n) ori
Dimensiunea datelor de intrare
Definiţii formale
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 de sortare prin inserţie
(Insertion Sort)
• Metoda de sortare prin inserţie este un algoritm eficient pentru sortarea
unui număr mic de elemente.

• Metoda de inserţii funcţionează în acelaşi mod în care se va sorta un set de


cărţi, selectând câte una luată la întâmplare. O singură carte la un moment
dat este scoasă din set şi este introdusă în mâna stângă în poziţia corectă
comparativ cu alte cărţi deja sortate. Pentru a găsi poziţia corectă pentru o
carte, aceasta este comparată cu fiecare dintre acele cărţi deja inserate.

• Pseudocodul pentru sortarea prin inserţie este INSERTION-SORT, care are


ca parametru un vector A [1... n] care conţine o secvenţă de lungimea n.
(În cod, numărul de elemente din A este notat cu length[A].)

• Numerele de intrare din vectorul A sunt sortate în secvenţa de ieşire, atunci


când ciclul din INSERTION- SORT este terminat.
Metoda de sortare prin inserţie
Algoritmul de inserţie solicită:

1. Începerea cu primul element din şirul de intrare.


2. Deplasarea elementelor din şirul de intrare până când şirul va deveni vid, a
se selecta primul element rămas (cel mai din stânga).
3. Compararea elementului selectat cu şirul curent sortat deja, pornind de la
elementul cel mai din dreapta şi deplasându-l spre stânga până la găsirea
poziţiei corecte în şirul sortat.
4. Dacă elementul selectat (eliminat) este mai mic decât elementul de
comparare, atunci se copie valoarea elementului selectat în poziţia
precedentă a elementului de comparare.
5. În caz contrar, noul element se află în poziţia corectă şi trebuie salvat în
celula corespunzătoare. Se reia procedura de la pasul (2) cu următorul
element din şirul de intrare.

• Subşirul ce conţine elementele deja sortate creşte la fiecare iteraţie, astfel


după ce parcurgem toate elementele, secvenţa este sortată în întregime.
Metoda de sortare prin inserţie
(Insertion Sort). Pseudocod
• INSERTION-SORT (A)
1. for j <- 2 to length[A]
2. do key <- A[j] // fixarea elementului j
3. Insert A[j] into the sorted sequence A[1 . . j - 1].
4. i <- j - 1
5. while i > 0 and A[i] > key // căutarea poziţiei
6. do A[i + 1] <- A[i] // deplasarea elementelor spre dreapta
7. i <- i - 1
8. A[i + 1] <- key // înregistrarea elementului key pe poziţia stabilită
Metoda de sortare prin inserţie
Eficienţa
Metoda de sortare prin inserţie
Eficienţa
Metoda de sortare prin inserţie
Eficienţa

• Cel mai favorabil caz: 1, 2, 3, … , n; Cel mai nefavorabil: n, n − 1, … , 1


• Algoritmul de sortare prin inserţie este stabil!
• Este foarte simplu de implementat (există implementări in 5 linii de cod)!
• Recomandat pentru şiruri restrânse de elemente (performanţe practice
bune!)
Metoda de sortare prin inserţie
Exemple
Exemplul 1 Exemplul 2
• 4 3 51 2
• 4|3 51 2
• 4|3 51 2
• 34|51 2
• 345|1 2
• 1 34 5|2
• 1 2 3 4 5|
Exemplul 3
Metoda de sortare prin selecţie
(Selection Sort)
• Selection sort (Metoda de sortare prin selecţie), după cum îi
spune şi numele, este un algoritm de sortare prin selecţie.
Este un algoritm simplu, care face Ο(n2) comparaţii, atât în
medie cât şi în cel mai rău caz. Este considerat ineficient
pentru liste de intrare mari, dar poate fi potrivit pentru liste de
intrare de dimensiuni mici. Algoritmul nu este stabil.
• Paşii acestuia sunt:
• Găseşte cel mai mic element din lista de intrare.
• Pune acest element pe prima poziţie din lista de intrare.
• Repetă paşii anteriori pentru elementele care au rămas,
aşezând minimurile din fiecare parcurgere pe poziţiile
următoare.
Metoda de sortare prin selecţie
(Selection Sort). Pseudocod

• SELECTION-SORT(A)
1. for j ← 1 to n-1
2. smallest ← j
3. for i ← j + 1 to n
4. if A[ i ] < A[ smallest ]
5. smallest ← i
6. Exchange A[ j ] ↔ A[ smallest ]
Metoda de sortare prin selecţie
Eficienţa
Metoda de sortare prin selecţie
Eficienţa
Metoda de sortare prin selecţie
Eficienţa

• Număr redus de deplasări elemente! (faţă de Sortarea prin inserţie).

• Algoritmul de sortare prin selecţie nu este stabil!


Metoda de sortare prin selecţie
Exemple.
Exemplul 1 Exemplul 2

• 4 3 51 2
• 1| 3542
• 1 2|543
• 1 2 3|45
• 1 2 34|5
• 1 2 3 4 5
Metoda Heap (piramidală, arborescentă) de
sortare (Heap Sort)

Heapsort este un algoritm care face parte din familia algoritmilor de sortare prin
selecţie. Deşi este mai lent în practică decât Quicksort sau Mergesort,
acesta are avantajul de a avea atât numărul mediu de comparaţii cât şi
numărul maxim de comparaţii de Ο(n log (n)). Heapsort nu este un algoritm
stabil. Algoritmul este mai complex decât Quicksort sau Mergesort.
Paşii algoritmului sunt:
• Creează un arbore binar din elementele listei de intrare cu proprietatea că
fiecare nod din arbore va fi mai mare decât oricare dintre descendenţii
acestuia. Aceasta se numeşte şi heap property. Astfel nodul rădăcină va fi
cel mai mare element din arbore.
• Elementul rădăcină va fi scos / şters din arbore şi concatenat listei sortate.
• Se reface arborele în aşa fel încât cel mai mare element din arbore să
devină noua rădăcină. Aceasta se întâmplă prin operaţia de sift-up.
• Algoritmul se reia până când toate elementele au fost concatenate listei
sortate, iar arborele nu va mai conţine nici un element.
34
Metoda Heap de sortare. Pseudocod

http://www.algorithmist.com/index.php/Heap_sort
Metoda Heap de sortare. Pseudocod

Heapsort(A) {
BuildHeap(A)
for i <- length(A) downto 2 {
exchange A[1] <-> A[i]
heapsize <- heapsize -1
Heapify(A, 1)
}
BuildHeap(A) {
heapsize <- length(A)
for i <- floor( length/2 ) downto 1 Heapify(A, i)
}
Heapify(A, i) {
le <- left(i)
ri <- right(i)
if (le<=heapsize) and (A[le]>A[i])
largest <- le
else largest <- i
if (ri<=heapsize) and (A[ri]>A[largest])
largest <- ri
36
if (largest != i) {
Metoda Heap (piramidală, arborescentă) de sortare
Exemplu
Metoda Heap (Exemplu. Criteriu de selecţie)
Metoda Heap de sortare. Exemplu
Metoda Heap de sortare. Exemplu
Criteriu de selecţie (Min-Heap)
Î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.
Evaluarea algoritmilor
Pentru a evalua performanţa algoritmilor, putem utiliza
abordări diferite.

• Cel mai simplu mod este de a executa fiecare algoritm


pe mai multe exemple şi a compara timpul de execuţie.

• O altă modalitate este să estimăm matematic timpul de


execuţie prin determinarea numărului de operaţii
efectuate.
Note şi consideraţii
• Deşi compararea complexităţii teoretice a diferitor algoritmi face
impresia unei concluzii bine stabilite, această concluzie nu este
neapărat foarte corectă dacă ţinem cont de faptul că există diferiţi
factori care influenţează aprecierea algoritmilor. Numărul de operaţii
şi timpul real de execuţie sunt factorii cei mai importanţi.

• Studiul bazat exclusiv pe timpul de execuţie a programului de


sortare nu face o comparaţie absolută între fiecare dintre algoritmii
analizaţi.

• Mulţi alţi factori trebuie luaţi în considerare pentru a garanta o


aplicaţie sau un produs optimizat. Exemple de elemente care trebuie
luate în considerare includ acest factor, dar nu se limitează doar la
tipul de execuţie, dar şi la volumul de memorie utilizat, utilizarea
procesorului şi corectitudinea algoritmului.
• Un alt factor se bazează, de asemenea, pe sistemul informatic
disponibil, performanţa calculatorului.

• http://www.norsemathology.org/wiki/index.php?title=-WiP-_Lauren_Lykowski%27s_Project
Aprecierea algoritmilor de sortare

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

45
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).


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).

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