Sunteți pe pagina 1din 8

Metode de sortare

Se dau n numere ntregi, elemente ale unui vector a. Se cere s se aranjeze elementele
vectorului a n ordine cresctoare.
1. Sortare prin selecie direct
Sortarea prin selecia minimului (sau maximului) este metoda de ordonare prin selectarea
unui element i plasarea lui pe poziia sa final direct n tabloul A.
De exemplu, n caz de ordonare cresctoare, pornind de la primul element se caut valoarea
minim din tablou. Aceasta se aeaz pe prima poziie printr-o interschimbare ntre
elementul de pe prima poziie i elementul minim de pe poziia k. Apoi, se reia algoritmul,
pornind de la a doua poziie i se caut minimul ntre elementele a2, ..., an. Acesta se inter-
schimb cu al doilea dac este cazul. Procedeul se continu pn la ultimul element.
Pseudocodul algoritmului de sortare prin selecia minimului este:
Subalgoritm Selecie(n,a)
1: pentru i=1,n-1 execut:
2: min = a[i]
3: pentru j=i+1,n execut:
4: dac min > a[j] atunci
5: min = a[j]
6: k = j Sfd 4: Sfp 3:
7: dac min <> a[i] atunci
8: aux = a[i]
9: a[i] = a[k]
10: a[k] = aux Sfd 7: Sfp 1:
Exemplu
Fie tabloul A = (5, 0, 8, 7, 3).
Pas Tabloul A Element minim Poziia minimului Noul tablou A
i=1 (5, 0, 8, 7, 3) 0 2 (0, 5, 8, 7, 3)
i=2 (0, 5, 8, 7, 3) 3 5 (0, 3, 8, 7, 5)
i=3 (0, 3, 8, 7, 5) 5 5 (0, 3, 5, 7, 8)
i=4 (0, 3, 5, 7, 8) 7 4
Algoritmul se poate scrie i prin determinarea valorilor maxime i mutarea lor n tablou de la dreapta la
stnga, astfel rezultnd, de asemenea, un ir ordonat cresctor. Un astfel de algoritm este des utilizat
pentru c este mai simplu de reinut, n forma urmtoare:
Subalgoritm Selecie(n,a)
1: pentru i=1,n-1 execut:
2: pentru j=i+1,n execut:
3: dac a[i] > a[j] atunci
4: aux = a[i]
5: a[i] = a[j]
6: a[j] = aux sfd 3: sfp 2: sfp 1:
Complexitatea algoritmului: Pentru acest algoritm de sortare nu putem spune c exist caz
favorabil, nefavorabil sau mediu, deoarece numrul de pai efectuai este n(n-1)/2 indiferent de
structura datelor de intrare. Aadar, ordinul de complexitate este (n
2
). Numrul de comparri este tot
n(n-1)/2, ns pentru cazul n care irul este ordonat cresctor se vor face doar n atribuiri (se execut
doar instruciunea de atribuire 2:)
2. Sortarea prin inserie
Sortarea prin inserie, este un algoritm eficient pentru sortarea unui numr mic de obiecte. Sortarea
prin inserie funcioneaz n acelai fel n care muli oameni sorteaz un pachet de cri de joc. Se
ncepe cu pachetul aezat pe mas cu faa n jos i cu mna stng goal. Apoi, lum cte o carte de pe
mas i o inserm n poziia corect n mna stng. Pentru a gsi poziia corect pentru o carte dat, o
comparm cu fiecare dintre crile aflate deja n mna stng, de la dreapta la stnga (sau de la stnga
la dreapta), aa cum este ilustrat n Figura 2.1.

Figura 2.1 Modul de ordonare a crilor, folosind metoda sortrii prin inserie.
Pseudocodul pentru sortarea prin inserie este prezentat ca o procedur numit Sorteaz-Prin-Inserie,
care are ca parametru un vector A[1..n] coninnd un sir de lungime n care urmeaz a fi sortat. (Pe
parcursul codului, numrul de elemente ale lui A este notat prin lungime[A].) Numerele de intrare sunt
sortate pe loc, n cadrul aceluiai vector A, cel mult un numr constant dintre acestea sunt memorate n
zone de memorie suplimentare. Cnd Sorteaza-Prin-Inserie se termin, vectorul iniial A va conine
elementele irului de ieire sortat.
Subalgoritm Sorteaza-Prin-Inserie(A)
1: pentru j 2, lungime[A] executa
2: cheie A[j]
3: i j - 1
4: ct timp i > 0 i A[i] > cheie executa
5: A[i + 1] A[i]
6: i i 1 sfc 4:
7: A[i + 1] cheie {Insereaza A[j] n sirul sortat A[1..j - 1]} sfp 1:
Figura 2.2 ilustreaz modul de funcionare a acestui algoritm pentru A = (5, 2, 4, 6, 1, 3). Indicele j
corespunde crii care urmeaz a fi inserat n mna stnga. Elementele A[1..j - 1] corespund
mulimii de cri din mna, deja sortate, iar elementele A[j + 1..n] corespund pachetului de cri aflate
nc pe mas. Indicele se deplaseaz de la stnga la dreapta n interiorul vectorului. La fiecare iteraie,
elementul A[j] este ales din vector (linia 2). Apoi, plecnd de la poziia j - 1, elementele sunt, succesiv,
deplasate o poziie spre dreapta pn cnd este gsita poziia corecta pentru A[j] (liniile 36), moment
n care acesta este inserat pe poziia corect n vectorul ordonat (linia 7).
a1 a2 a3 a4 a5 a5
5 2 4 6 1 3
2 5 4 6 1 3
2 4 5 6 1 3
2 4 5 6 1 3
1 2 4 5 6 3
1 2 3 4 5 6
Figura 2.2 Modul de operare a procedurii Sorteaza-Prin-Inserie asupra vectorului A =(5, 2, 4, 6, 1, 3).
Poziia indicelui j este indicat prin colorarea celulei corespunztoare din tabelul din figur.
Complexitatea algoritmului: Sortarea prin inserie are un timp de execuie n cazul cel mai
defavorabil de (n
2
) (pronunat teta de n ptrat).
3. Metoda bulelor (bubble-sort)
Algoritmul const n parcurgerea tabloului A de mai multe ori, pn cnd devine ordonat. La fiecare pas
se compar dou elemente alturate. Dac a
i
> a
i + 1
, (i = 1, 2, ..., n 1), atunci cele dou valori se
interschimb ntre ele. Controlul aciunii repetitive este dat de variabila boolean ok, care la fiecare
reluare a algoritmului primete valoarea iniial adevrat, care se schimb n fals dac s-a efectuat o
interschimbare de dou elemente alturate. n momentul n care tabloul A s-a parcurs fr s se mai
efectueze nici o schimbare, ok rmne cu valoarea iniial adevrat i algoritmul se termin, deoarece
tabloul este ordonat.
Interschimbarea a dou elemente se realizeaz prin intermediul variabilei auxiliare aux care are acelai
tip ca i elementele tabloului.
Subalgoritm Metoda_bulelor (A)
1: repet
2: ok = adevrat
3: pentru i=1,n-1 execut
4: dac a[i] > a[i+1] atunci
5: ok = fals
6: aux = a[i]
7: a[i] = a[i+1]
8: a[i+1] = aux sfd 4: sfp 3:
9: pn cnd ok
Considerm tabloul A cu 5 elemente numere reale: 0.0, 1.1, 1.0, 1.2 i 0.08.
I. Prima parcurgere a tabloului (ok este iniializat cu adevrat):
a1 = 0.0 a2 = 1.1 a3 = 1.0 a4 = 1.2 a5 = 0.08 ok
0.0 1.0 1.1 1.2 0.08 fals
0.0 1.0 1.1 0.08 1.2 fals
Valorile 0.0 < 1.1, rmn neschimbate, 1.1 > 1.0, le interschimbm. Deoarece 1.1 < 1.2, avansm i
constatm c 1.2 > 0.0.8, deci din nou avem interschimbare. n consecin, la ieire din structura
pentru ok este fals. Observm c 1.2 a ajuns pe locul lui definitiv (elementul maxim).
II. Urmeaz a doua parcurgere a tabloului (ok primete din nou valoarea adevrat).
a1 = 0.0 a2 = 1.0 a3 = 1.1 a4 = 0.08 a5 = 1.2 ok
0.0 1.0 0.08 1.1 1.2 fals
Am avut interschimbare i de data aceasta, deci ieim cu ok = fals. La acest pas 1.1 a ajuns pe locul
su definitiv.
III. A treia parcurgere a tabloului ncepe cu reiniializarea lui ok cu valoarea adevrat.
a1 = 0.0 a2 = 1.0 a3 = 0.08 a4 = 1.1 a5 = 1.2 ok
0.0 0.08 1.0 1.1 1.2 fals
Am interschimbat 0.08 cu 1.0, cel din urm astfel a ajuns pe locul su n irul ordonat. A patra
parcurgere a tabloului se finalizeaz cu valoarea ok = adevrat, deoarece nu am efectuat nici o
interschimbare, ceea ce nseamn c procesul de ordonare s-a ncheiat.
a1 = 0.0 a2 = 0.08 a3 = 1.0 a4 = 1.1 a5 = 1.2 ok
0.0 0.08 1.0 1.1 1.2 adevrat
Observaia cu privire la faptul c la fiecare parcurgere a ajuns cel puin un element pe locul su definitiv
n irul ordonat poate fi fructificat, deoarece constatm c astfel, la urmtorul pas nu mai sunt
necesare verificrile n care intervine acest element i cele care se afl dup el n ir, acestea fiind deja
sortate cresctor. Rezult c la fiecare parcurgere am putea micora cu 1 numrul elementelor
verificate. Dar este posibil ca la o parcurgere s ajung mai multe elemente n locul lor definitiv.
Rezult c vom ine minte indicele ultimului element care a intervenit n interschimbare i verificrile le
vom efectua doar pn la acest element. Astfel, ajungem la urmtorul subalgoritm mbuntit ca
performan:
Subalgoritm Metoda_bulelor (A)
1: k=n {k va fi limita superioar pn unde se interschimb elemente}
2: repet
3: ok = adevrat
4: pentru i=1,k-1 execut
5: dac a[i] > a[i+1] atunci
6: ok = fals
7: aux = a[i]
8: a[i] = a[i+1]
9: a[i+1] = aux
10: j=i
11: k=j; {ultimul indice pentru care s-a facut interchimbare}
12: pn cnd ok
Complexitatea algoritmului: Metoda bulelor nu este cea mai performant modalitate de a ordona un
ir cu multe elemente, dar n cazul irurilor aproape ordonate, cu optimizrile de mai sus, poate
deveni mai eficient dect alte metode.
Pentru a analiza timpul de execuie al metodei bulelor trebuie s lum n considerare 3 mrimi:
1. numrul de treceri (parcurgeri)
2. numrul de interschimbri
3. numrul de comparaii
Dac presupunem c valorile de intrare reprezint o permutare a mulimii {1, 2, ..., n} putem uor
descrie efectul fiecrei treceri astfel: dac un element ai nu are nici un precedent mai mare el va
rmne pe loc, iar daca are cel puin unul mai mare atunci el se va muta cu o poziie mai n fa.
Reamintesc c elementul maxim de la fiecare parcurgere va ajunge pe poziia final. Astfel, eficiena
metodei bulelor depinde de numrul de inversiuni din permutarea iniial (fa de permutarea final,
cea identic). Voi defini n continuare inversiunea i proprietile inversiunilor.
Definiie: Fie a1, a2, ... an o permutare a mulimii {1, 2, ..., n}. Dac i<j i ai>aj, atunci perechea (ai,
aj) se numete inversiunii a permutrii. De exemplu, n permutarea 3,1,4,2 se gsesc 3 inversiuni:
(3,1), (3,2) i (4,2).
Observaie: Singura permutare fr inversiuni este cea ordonat (identic) 1,2,...,n.
Cazul cel mai favorabil este acela n care datele iniiale sunt ordonate cresctor, caz n care se face o
singur parcurgerea a datelor.
Cazul cel mai nefavorabil este cel n care datele sunt sortate descresctor, caz n care se vor face n-1
parcurgeri. La prima parcurgere se vor face n-1 interschimbri, la a doua n-2 i aa mai departe.
Aadar numrul de comparaii i cel de interschimbri va fi n(n-1)/2. Exemplu n acest caz:

Numrul parcurgerii
a1 a2 a3 a4 Numrul de interschimbri
iniial 4 3 2 1
1 3 2 1 4 3
2 2 1 3 4 2
3 1 2 3 4 1
Total interschimbri 6
Astfel, vom spune c metoda bulelor are un timp de execuie n cazul cel mai defavorabil de (n
2
).

4. Sortare prin numrare
Aceast metod const n construirea unui nou tablou B care are aceeai dimensiune ca i tabloul A n
care vom memora elementele din A, ordonate cresctor.
Vom lua fiecare element i l vom compara cu fiecare alt element din ir pentru a putea reine n
variabila k numrul elementelor care sunt mai mici dect elementul considerat. Astfel, vom afla poziia
pe care trebuie s-l punem pe acesta n irul B. Dac n problem avem nevoie de irul ordonat tot n
tabloul A, vom copia n A ntreg tabloul B.
Subalgoritm Numrare(n,A)
1: pentru i=1,n execut
2: k = 0
3: pentru j=1,n execut
4: dac (A[i] > A[j]) atunci
5: k = k + 1 { numrm cte elemente sunt mai mici dect A[i] }
6: B[k+1] = A[i] { pe A[i] l punem pe poziia corespunztoare din B } sfd 4: sfp 3:
7: A = B { copiem peste irul A ntreg irul B }
Exemplu
Fie tabloul A cu 4 elemente: 7, 2, 3, 1.
i j Relaia k bk + 1
1 1 i = j 0
1 2 7 > 2 1
1 3 7 > 3 2
1 4 7 > 1 3 b4 = 7
2 1 2 < 7 0
2 2 i = j 0
2 3 2 < 3 0
2 4 2 > 1 1 b2 = 2
3 1 3 < 7 0
3 2 3 > 2 1
3 3 i = j 1
3 4 3 > 1 2 b3 = 3
4 1 1 < 7 0
4 2 1 < 2 0
4 3 1 < 3 0
4 4 i = j 0 b1 = 1
Algoritmul funcioneaz n aceast form dac elementele tabloului A sunt distincte, altfel n
B vor rmne elemente necopiate din A, deoarece dou elemente egale se vor copia n B pe aceeai
poziie. De exemplu, pentru un tabloul A cu 4 elemente: 7, 2, 3, 3 se va obine 2, 3, 0, 7 dac n B am
avut iniial doar elemente nule.
Aceast situaie se poate remedia n 2 moduri:
1. mai parcurgem o dat irul final i toate elementele care nu respect relaia de ordine le modificm
atribuindu-le valoarea din stnga. Astfel, din irul 2, 3, 0, 7 vom obine 2, 3, 3, 7.
Algoritmul modificat este urmtorul:
Subalgoritm Numrare(n,a)
1: pentru i=1,n execut
2: k = 0
3: pentru j=1,n execut
4: dac (a[i] > a[j]) atunci
5: k = k + 1
6: b[k+1] = a[i] sfd 4: sfp 3: sfp 1:
7: a = b
8: pentru i=1,n-1 execut
9: dac a[i] >= a[i+1] atunci
10: a[i+1] = a[i] sfd 9: sfp 8
2. nainte de atribuirea b[k+1] = a[i] verificm dac b[k+1] = a[i] i ct timp e fals mrim pe k.
Rezultatul este acelai.
Algoritmul modificat este urmtorul:
Subalgoritm Numrare(n,a)
1: pentru i=1,n execut
2: k = 0
3: pentru j=1,n execut
4: dac (a[i] > a[j]) i (i <> j) atunci
5: k = k + 1
6: ct timp b[k+1] = a[i] execut {cat timp n B a fost deja pus un element cu aceeasi valoare}
8: k = k + 1
9: b[k+1] = a[i]
10: a = b
Complexitatea algoritmului: Pentru acest algoritm de sortare nu putem spune c exist caz
favorabil, nefavorabil sau mediu, deoarece numrul de pai efectuai este n
2
indiferent de structura
datelor de intrare. Aadar, ordinul de complexitate este (n
2
).

5. Algoritmi liniari de sortare
5.1 Sortarea prin numrarea apariiilor
Algoritmii prezentai anterior sunt relativ mari consumatori de timp. De exemplu, pentru a ordona un
ir de 1000 de elemente, numrul comparaiilor pe care le va executa oricare dintre algoritmii
prezentai va fi aproximativ de 1 milion. Un algoritm liniar execut un numr de operaii proporional cu
numrul elementelor, adic pentru a ordona 1000 de elemente vor fi necesare c < 1000 de operaii,
unde c este o constant. n anumite condiii asupra datelor de intrare se pot construi algoritmi liniari
pentru sortare.
Dac avem un ir de elemente de tip ordinal care sunt dintr-un interval de cardinalitate nu foarte mare,
vom putea realiza o ordonare liniar. Corespunztor fiecrei valori ntlnite n ir n timpul prelucrrii
mrim cu 1 valoarea elementului avnd indicele (n acest ir de contoare) egal cu valoarea elementului
n irul de ordonat. n final, vom suprascrie n irul dat attea elemente cu valori ai indicilor elementelor
diferite de 0 ct este valoarea elementului n acest ir a numerelor de apariii.
Important este s reinem particularitile pe care trebuie s le aib irul dat pentru ca aceast metod
s se poat aplica:
valorile elementelor trebuie s fie de tip ordinal (adic numere ntregi);
numrul elementelor mulimii din care irul primete valori trebuie s fie relativ mic, astfel
nct, n funcie de limbajul de programare n care vom implementa algoritmul s nu se
depeasc memoria maxim alocat unui vector;
valorile posibile n irul de ordonat trebuie s fie din intervalul [x..y], unde y x + 1 va fi
dimensiunea irului de contoare.

Exemplu
Presupunem c toate valorile din vectorul de sortat sunt numere naturale <=1000.
Vom folosi un vector de frecvene f.
Subalgoritm Ordonare_cu_ir_de_Frecvene(n,a,x,y):
1: x = 0
2: y = 1000
3: pentru i=x,y execut
f[i] = 0 {iniializeaz frecvenele cu 0} sfp 3:
4: pentru i=1,n execut:
f[A[i]] = f[A[i]] + 1 {mrete frecvena fiecrui element din A} sfp 4:
5: k = 0
6: pentru i=x,y execut:
7: pentru j=1,f[i] execut:
8: k = k + 1
9: A[k] = i {pune napoi n A fiecare element de cte ori este frecvena lui} sfp 7: sfp 6:
Fie irul (2, 1, 1, 0, 2, 3, 0, 2).
Valorile elementelor sunt numere naturale 0,1,2,3. irul de frecvene construit de algoritmul de mai sus
va fi va fi f=(2, 2, 3, 1), f[0]=2, f[1]=2,f[2]=3,f[3]=1.
Corespunztor ultimei secvene din algoritm se vor scrie dou valori 0 consecutive n a, apoi 2 elemente
egal cu 1, urmeaz trei elemente de 2, urmat de o valoare 3: 0, 0, 1, 1, 2, 2, 2, 3.
Dei este un algoritm liniar, eficiena lui trebuie bine studiat nainte de a-l aplica. Eficienta depinde
att de numrul de valori din vectorul iniial, ct i de valorile propriu-zise. Algoritmul depinde liniar de
n, numrul de valori din vector, dar capacitatea de memorie necesar pentru vectorul de frecvene i
apoi numrul de pai ai instruciunii 6: depinde de limitele n care se afl valorile din ir, iar n funcie
de acestea, algoritmul poate deveni mai puin eficient dect unul cu ordin ce complexitate (n
2
). Un
exemplu n acest caz, dac vrem s ordonm 100 de numere din intervalul [1, 15.000]. O ordonare
(n
2
) ar face maxim 10000 de pai, iar ordonarea cu frecvene face 15.000, ca s nu mai vorbim de
risipa de memorie care se face n cazul folosirii vectorului de frecvene.
5.2 Sortarea prin numrarea apariiilor i a elementelor mai mici
Acest algoritm poate fi privit ca o variant a algoritmului anterior, obinut prin numrarea i a
elementelor mai mici, nu doar a frecvenei de apariie.
Sortarea prin numrare presupune c fiecare dintre cele n elemente ale datelor de intrare este un
numr ntreg ntre 1 i k, pentru un numr ntreg k oarecare. Cnd k = (n), sortarea se executa n
timpul (n).
Ideea de baza n sortarea prin numrare este de a determina numrul de elemente mai mici dect x,
pentru fiecare element x din datele de intrare. Aceast informaie poate fi utilizat pentru a poziiona
elementul x direct pe poziia sa din tabloul de ieire. De exemplu, dac exist 17 elemente mai mici
dect x, atunci x va fi pe poziia 18 n tabloul de ieire. Aceast schem trebuie uor modificat n
situaia n care exist mai multe elemente avnd aceeai valoare, ntruct nu dorim s le aezm pe
toate n aceeai poziie.
n algoritmul pentru sortarea prin numrare presupunem c datele de intrare formeaz un tablou
A[1..n], i deci lungime [A] = n. Sunt necesare alte doua tablouri suplimentare, tabloul B [1..n], care
cuprinde datele de ieire sortate, i tabloul C [1..k], pentru stocarea temporara n timpul lucrului.
Subalgoritm Sortare-Prin-Numarare(A,B, k)
1: pentru i 1, k execut
2: C [i] 0
3: pentru j 1, lungime [A] execut
4: C [A[j]] C [A[j]] + 1
5: { C[i] conine acum numrul elementelor egale cu i.} sfp 3:
6: pentru i 2, k execut
7: C [i] C [i] + C [i - 1]
8: { C[i] conine numrul elementelor mai mici sau egale cu i.} sfp 6:
9: pentru j lungime [A] , 1,-1 execut
10: B [C [A[j]]] A[j]
11: C [A[j]] C [A[j]] - 1
Algoritmul de sortare prin numrare este ilustrat n figura 5.2.1. Dup iniializarea din liniile12, n
liniile 34 se contorizeaz fiecare element de intrare. Dac valoarea unui element de intrare este i, se
incrementeaz valoarea lui C [i]. Astfel, dup liniile 34, C[i] pstreaz un numr de elemente de
intrare egal cu i pentru fiecare numr ntreg i = 1,2, , k. n liniile 67 se determin, pentru fiecare
i = 1, 2, , k, numrul elementelor de intrare mai mici sau egale dect i, aceasta se realizeaz prin
pstrarea n C[k] a sumei primelor k elemente din tabloul iniial.
n final, n liniile 911, fiecare element A[j] se plaseaz pe poziia sa corect determinat din tabloul de
ieire B, astfel nct acesta este ordonat. Dac toate cele n elemente sunt distincte, la prima execuie a
liniei 9, pentru fiecare A[j], valoarea C[A[j]] este poziia final corect a lui A[j] n tabloul de ieire,
ntruct exist C [A[j]] elemente mai mici sau egale cu A[j]. Deoarece elementele ar putea s nu fie
distincte, decrementm valoarea C[A[j]] de fiecare dat cnd plasm o valoare A[j] n tabloul B,
aceasta face ca urmtorul element de intrare cu o valoare egal cu A[j], dac exist vreunul, s mearg
n poziia imediat dinaintea lui A[j] n tabloul de ieire.

Ct timp necesita sortarea prin numrare? Bucla pentru din liniile 12 necesit timpul (k), bucla
pentru din liniile 34 necesit timpul (n), bucla pentru din liniile 67 necesit timpul (k), iar bucla
pentru din liniile 911 necesit timpul (n). Deci timpul total este (k + n). n practic se utilizeaz
sortarea prin numrare cnd avem k = (n), caz n care timpul necesar este (n).
O proprietate important a sortrii prin numrare este stabilitatea: numerele cu aceeai valoare apar n
tabloul de ieire n aceeai ordine n care se gsesc n tabloul de intrare. Adic, legturile dintre dou
numere sunt distruse de regula conform creia oricare numr care apare primul n vectorul de intrare,
va aprea primul i n vectorul de ieire. Desigur, stabilitatea este importanta numai cnd datele
nvecinate sunt deplasate mpreuna cu elementul n curs de sortare.

Figura 5.2.1 Modul de funcionare al algoritmului Sortare-Prin-Numarare pe un tablou A[1..8] de
intrare, unde fiecare element din tabloul A este un numr ntreg pozitiv nu mai mare dect k = 6.
(a) Tabloul A i tabloul auxiliar C dup executarea liniei 4. (b) Tabloul C dup executarea liniei 7.
(c)-(e) Tabloul de ieire B i tabloul auxiliar C dup unul, dou, respectiv trei iteraii ale buclei din liniile
911. Doar elementele haurate din tabloul B au fost completate. (f) Tabloul B sortat, furnizat la ieire.