Curs 5 - Agenda
sortare interna
“buble sort”
sortare prin insertie
sortare pri selectie
naiva
sistematica (“heap sort”)
sortare prin interclasare (“merge sort”)
sortare rapida (“quick sort”)
cautare
in liste liniare
cautare binara – aspectul dinamic
arbori AVL
Problema sortarii
Forma 1
Intrare: n, (R0, . . . , Rn-1) cu cheile k0, . . . , kn-1
Iesire: (R’0, . . . , R’n-1) astfel incit (R’0, . . . , R’n-1) este o permutare a
(R0, . . . , Rn-1 ) si R’0.k0 ≤ . . . ≤ R’n-1.kn-1
Forma 2
Intrare: n, (v0, . . . , vn-1)
Iesire: (w0, . . . , wn-1) astfel incit (w0, . . . , wn-1) este o permutare a (v0, . . . , vn-1), si w0 ≤ . . . ≤ wn-1
structura de date array a[0..n-1]
a[0] = v0, . . . , a[n-1] = vn-1
Bubble sort I
idee:
(∀i) 0 ≤ i < n-1 ⇒ a[i] ≤ a[i+1]
algoritm
procedure bubbleSort (a, n) begin
ultim ← n-1
while ultim > 0 do ntemp ← ultim – 1 ultim ← 0
for i ← 0 to ntemp do if a[i] > a[i+1]
then swap(a[i], a[i+1]) ultim ← i
end
Bubble sort II
exemplu
analiza
cazul cel mai nefavorabil a[0] > a[1] > ... > a[n-1]
TbubleSort(n) = O(n2)
Sortare prin insertie directa I
idee
presupunem a[0..i-1] sortat
insereaza a[i] astfel incit a[0..i] devine sortat
algoritm
procedure insertSort(a, n) begin
for i ← 1 to n-1 do j ← i – 1
temp ← a[i]
while ((j ≥ 0) and (a[j] > temp)) do a[j+1] ← a[j]
j ← j – 1
if (a[j+1] ≠ temp) then a[j+1] ← temp
end
Sortare prin insertie directa II
exemplu
analiza
cazul cel mai nefavorabil a[0] > a[1] > ... > a[n-1]
TinsertSort(n) = O(n2)
Sortare prin selectie
ideea de baza
pasul curent: selecteaza un element si-l duce pe pozitia sa finala din tabloul sortat
repeta pasul curent pana cnd toate elementele ajung pe locurile finale
Sortare prin selectie naiva
idee
(∀i ) 0 ≤ i < n ⇒ a[i] = max{a[0],…,a[i]}
algoritm
procedure naivSort(a, n) begin
for i ← n-1 downto 0 do imax ← i
for j ← i-1 downto 0 do if (a[j] > a[imax]) then imax ← j
if (i ≠ imax) then swap(a[i], a[imax]) end
complexitatea timp toate cazurile:
TnaivSort(n) = Θ(n2)
"Heap sort" (sortare prin selectie sistematica)
etapa I
organizeaza tabloul ca un max-heap
initial tablou satisface proprietatea max- heap incepand cu n/2
introduce in max-heap elementele de pe pozitiile n/2-1, n/2 -1, …, 1, 0
etapa II
selecteaza elementul maxim si-l duce la locul lui prin interschimbare cu ultimul
micsoreaza cu 1 si apoi reface max-heapul
repeta pasii de mai sus pana cand toate elementele ajung pe locul lor
Operatia de introducere in heap al t-lea
procedure insereazaAlTlea(a, n, t) begin
j ← t
heap ← false
while ((2*j+1 < n) and not heap) do k ← 2*j+1
if ((k < n-1) and (a[k] < a[k+1])) then k ← k+1
if (a[j] < a[k])
then swap(a[j], a[k]) j ← k
else heap ← true end
"Heap sort" (sortare prin selectie sistematica)
procedure heapSort(a, n) begin
// construieste maxheap-ul for t ← (n-1)/2 downto 0 do
insereazaAlTlea(a, n, t) // elimina
r ← n-1
while (r > 0) do
swap(a[0], a[r])
insereazaAlTlea(a, r, 0) r ← r-1
end
"Heap sort" - complexitate
formarea heap-ului (pp. )
eliminare din heap si refacere heap
complexitate algoritm de sortare
) 1 (
2 2
2 ) 1 (
2
11 0
+
−
=
−
−
+−
∑
k=k i
i kk
i1 2 −
= k n
4 2
) 2 (
2
2
11 0
+
−
=
+−
∑
k= i k ik i
) log (
2 log
2 )
heapSort
( n n n n O n n
T = − =
Timpul de executie empiric
Intel Pentium III 1.00 Ghz
0.0160 0.5780
0.4060 3.0940
10000
0.0160 0.3590
0.2500 1.9530
8000
0.0160 0.0930
0.0630 0.4840
4000
0.0000 0.0320
0.0150 0.1100
2000
0.0000 0.0150
0.0000 0.0310
1000
0.0000 0.0000
0.0000 0.0000
100
0.0000 0.0000
0.0000 0.0000
10
heapSort naivSort
insertSort bubbleSort
n
Paradigma divide-et-impera
P(n): problema de dimensiune n
baza
daca n ≤ n0 atunci rezolva P prin metode elementare
divide-et-impera
divide P in a probleme P1(n1), ..., Pa(na) cu ni ≤ n/b, b > 1
rezolva P1(n1), ..., Pa(na) in aceeasi maniera si obtine solutiile S1, ..., Sa
asambleaza S1, ..., Sa pentru a obtine solutia S a problemei P
Paradigma divide-et-impera: algoritm
procedure DivideEtImpera(P, n, S) begin
if (n <= n0)
then determina S prin metode elementare
else imparte P in P1, ..., Pa DivideEtImpera(P1, n1, S1) ...
DivideEtImpera(Pa, na, Sa) Asambleaza(S1, ..., Sa, S) end
Sortare prin interclasare (Merge sort)
generalizare: a[p..q]
baza: p ≥ q
divide-et-impera
divide: m = [(p + q)/2]
subprobleme: a[p..m], a[m+1..q]
asamblare: interclaseaza subsecventele sortate a[p..m] si a[m+1..q]
initial memoreaza rezultatul interclasarii in temp
copie din temp[0..p+q-1] in a[p..q]
complexitate:
timp : T(n) = O(n log n) (T(n) = 2T(n/2)+n)
spatiu suplimentar: O(n)
Interclasarea a doua secvente sortate
problema:
date a[0] ≤ a[1] ≤ … ≤ a[m-1], b[0] ≤ b[1] ≤ … ≤ b[n-1],
sa se construiasca c[0] ≤ c[1] ≤ … ≤ c[m+n-1]
a.i. (∀ k)((∃i)c[k]=a[i]) ∨ (∃j)c[k]=b[j])
solutia
initial: i ← 0, j ← 0, k ← 0
pasul curent:
daca a[i] ≤ b[j]
atunci c[k] ← a[i], i ← i+1
daca a[i] > b[j]
atunci c[k] ← b[j], j ← j+1
k ← k+1
conditia de terminare: i > m-1 sau j > n-1
daca e cazul, copie elementele din tabloul neterminat
Sortare rapida (Quick sort)
generalizare: a[p..q]
baza: p ≥ q
divide-et-impera
divide: determina k intre p si q prin
interschimbari a.i. dupa determinarea lui k avem:
p ≤ i ≤ k ⇒ a[i] ≤ a[k]
k < j ≤ q ⇒ a[k] ≤ a[j]
Ösubprobleme: a[p..k-1], a[k+1..q]
Öasamblare: nu exista
x k
p q
≤ x ≥ x
Quick sort: partitionare
initial:
x ← a[p] (se poate alege x arbitrar din a[p..q])
i ← p+1 ; j ← q
pasul curent:
daca a[i] ≤ x atunci i ← i+1
daca a[j] ≥ x atunci j ← j-1
daca a[i] > x > a[j] si i < j atunci
swap(a[i], a[j])
i ← i+1
j ← j-1
terminare:
conditia i > j operatii k ← i-1
swap(a[p], a[k])
Cautare
in liste liniare
cautare binara – aspectul dinamic
arbori AVL
Problema cautarii
aspectul static
U multime univers S ⊂ U
operatia de cautare:
Instanta: a ∈ U Intrebare: a ∈ S?
aspectul dinamic
operatia de inserare Intrare: x ∈ U, S
Iesire: S ∪ {x}
operatia de stergere Intrare: x ∈ U, S
Iesire: S − {x}
Cautare in liste liniare - complexitate
O(1) O(n)
O(n) Liste inlantuite
O(n) O(n)
O(log n) Tablouri
Lista liniara ordonata
O(1) O(1)
O(n) Liste inlantuite
O(n) O(1)
O(n) Tablouri
Lista liniara
Stergere Inserare
Cautare Implementare
Tip de date
Cautare binara – aspect static - context
multimea univers este total ordonata: (U, ≤)
structura de data utilizata:
array s[0..n-1]
s[0]< ... < s[n-1]
Cautare binara – aspect static - algoritm
function Poz(s, n, a) begin
p ← 0; q ← n-1 m ← [(p+q)/2]
while (s[m] != a && p < q) do if (a < s[m])
then q ← m-1 else p ← m+1 m ← [(p+q)/2]
if (s[m] = a) then return m else return -1;
end
Arborele binar asociat cautarii binare
T(p,q) m
T(p,m-1) T(m+1,q)
T = T(0,n-1) n = 6
1 3 5
4 2
0
Cautare binara: aspect dinamic
arbore binar de cautare
ª arbore binar cu proprietatea ca pentru orice nod v, valorile memorate in
subarborele la stinga lui v
<
valoarea din v
<
valorile memorate in subarborele la dreapta lui v.
Cautare binara: aspect dinamic - cautare
function Poz(t, a) begin
p ← t
while (p != NULL && p->val != a) do if (a < p->val)
then p ← p->stg else p ← p->drp return p
end
Cautare binara: aspect dinamic - inserare
procedure insArbBinCautare(t, x) begin
if (t = NULL)
then t ← (x) /*(x) e arborele cu 1 nod */
else p ← t
while (p != NULL) do predp ← p
if (x < p->val) then p ← p->stg
else if (x > p->val)then p ← p->drp else p ← NULL
if (predp->val != x) then if (x < predp->val)
then adauga x ca fiu stinga a lui predp else adauga x ca fiu dreapta a lui predp end
Cautare binara: aspect dinamic - eliminare
se cauta pentru x in arborele t; daca-l gaseste se disting cazurile:
• cazul 1: nodul p care memoreaza x nu are fii
• cazul 2: nodul p care memoreaza x are un singur fiu
• cazul 3: nodul p care memoreaza x are ambii fii
– determina nodul q care memoreaza cea mai mare valoare y mai mica decit x
(coboara din p la stinga si apoi coboara la dreapta cit se poate)
– interschimba valorile din p si q – sterge q ca in cazul 1 sau 2
Cautare binara: aspect dinamic - eliminare
cazul 1 sau 2
procedure elimCaz1sau2(t, predp, p) begin
if (p = t)
then t devine vid sau unicul fiu al lui t devine radacina
else if (p->stg = NULL)
then inlocuieste in predp pe p cu p->drp else inlocuieste in predp pe p cu p->stg end
Cautare binara: aspect dinamic - eliminare
procedure elimArbBinCautare(t, x) begin
if (t != NULL) then p ← t
while (p != NULL && p->val != x) do predp ← p
if (x < p->val) then p ← p->stg else p ← p->drp
if (p != NULL)
if (p->stg = NULL || p->drp = NULL) then elimCaz1sau2(t, predp, p)
else q ← p->stg; predq ← p while (q->drp != NULL)
predq ← q; q ← q->drp p->val ← q->val
elimCaz1sau2(t, predq, q) end
Degenerarea cautarii binare in cautare liniara
30 50 40 10
0
20
30 50 40 20
30 50 0 40
20
30 40 20
30 40 20
35
30 40 20
35 32
elimina(10) elimina(0) elimina(50)
insereaza(35) insereaza(32)
Arbori AVL
un arbore binar de cautare t este un arbore AVL-echilibrat daca pentru orice virf v,
h(v→stg) − h(v→drp)≤ 1
Lema
t AVL-echilibrat ⇒ h(t) = Θ(log n).
Arbori AVL
Teorema
Clasa arborilor AVL-echilibrati este O(log n) stabila.
algoritmul de inserare
nodurile au memorate si factorii de echilibrare (∈ {−1, 0, 1})
se memoreaza drumul de la radacina la nodul adaugat intr-o stiva (O(log n))
se parcurge drumul memorat in stiva in sens invers si se reechilibeaza nodurile dezichilibrate cu una dintre operatiile:
rotatie stinga/dreapta simpla/dubla (O(log n)).
Rotatii
x
y x
y A
A
B B
C
C Rotatie dreapta simpla
Rotatie dreapta dubla x
y z
x
y
z A
B A B
C C
D
D