Documente Academic
Documente Profesional
Documente Cultură
ana
7 (1216 noiembrie 2012)
Semigrupele 1312, 1322, 1332 Sapt
laborator
4
Structuri arborescente I
Coninut
99999999999999999999999999999999999999999999
Arbori
99999999999999999999999999999999999999999999
Arbori binari
99999999999999999999999999999999999999999999
Arbori binari de cutare
99999999999999999999999999999999999999999999
Arbori binari de cutare indexai
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
>>
Referine
99999999999999999999999999999999999999999999
T.H. Cormen, C.E. Leiserson, R.L. Rivest. Introducere n
algoritmi: cap 5.5, cap.11.4, cap 13, Editura Computer Libris Agora, 2000 (i ediiile ulterioare)
99999999999999999999999999999999999999999999
R. Ceterchi. Materiale de curs, Anul universitar 20122013
99999999999999999999999999999999999999999999
http://laborator.wikispaces.com/, Tema 6
99999999999999999999999999999999999999999999
D.E. Knuth. Tratat de programare a calculatoarelor - Sortare i cutare, Editura Tehnic, 1973 (i ediiile ulterioare)
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
Arbori
Un arbore T este un graf neorientat, conex i aciclic, cu un nod evideniat ce se numete rdcin
i pe care l vom nota root.
Dac eliminm o muchie oarecare din arbore obinem un graf care nu mai este conex.
Dac adugm o muchie oarecare n arbore obinem un graf care nu mai este aciclic.
Un arbore este un graf conex n care numrul de muchii |E| este egal cu numrul de vrfuri
|V | minus 1.
Un arbore este un graf aciclic n care numrul de muchii |E| este egal cu numrul de vrfuri
|V | minus 1.
Terminologie
Fie x un nod din arborele T .
Orice nod y pe drumul unic dintre root i x se numete strmo al lui x. Reciproc, x este un
descendent al lui y. (Fiecare nod este considerat att strmo ct i descendent al lui nsui.)
Subarborele cu rdcina x este arborele alctuit din nodul x ca rdcin i toi descendenii
acestuia.
Dac pe drumul de la rdcin la x ultima muchie este (y, x ), atunci y se numete printele
sau tatl lui x, iar x se numete fiul sau copilul lui y. Dou noduri cu acelai printe se numesc
frai.
Un nod fr fii se numete nod extern sau frunz. Un nod care nu este nod extern se numete
nod intern.
Gradul unui nod este numrul de fii al acestuia.
nlimea h a unui arbore este definit ca lungimea maxim a unui drum de la rdcin la
o frunz. Prin lungime se nelege numrul de muchii care sunt parcurse n drumul respectiv.
Arborele vid are nlime 0, arborele care conine doar un singur nod (rdcina) are nlime 0, un
arbore care conine dou noduri (rdcina i unul din fii ei) are nlime 1, etc.
Putem asocia niveluri nodurilor din arbore n modul urmtor: toate nodurile aflate la adncime 0 i h se afl la nivelul i, ca n figur. Adncimea unui nod x este lungimea drumului
(numrul de muchii) de la root la x (adncimea rdcinii este 0). Deci nlimea arborelui este cea
mai mare adncime a unui nod din el.
Se numete arbore ordonat un arbore cu rdcin n care fii oricrui nod sunt ordonai, mai
exact dac nodul are k fii, atunci exist un prim fiu, un al doilea fiu, etc.
59
nivel 0
n
alt
imea h = 4
11
12
nivel 1
10
Figur 1
nivel 2
nivel 3
nivel 4
Arbori binari
Un arbore binar T este o structur definit pe o mulime finit de noduri, care:
fie nu conine niciun nod,
fie conine:
- un nod rdcin,
- un abore binar numit subarborele stng i
- un arbore binar numit subarbore drept.
Cu alte cuvinte, este vorba despre un arbore cu cel mult doi fii, numii fiu stng, respectiv fiu
drept.
Un arbore binar complet este un arbore binar n care fiecare nod este fie o frunz (de obicei
reprezentat printr-un ptrat), fie are gradul exact 2 (niciunul din fii nu lipsete). Dintr-un arbore
binar se poate obine un arbore binar complet, nlocuind fiecare fiu absent al unui nod cu o frunz.
60
s t r u c t nod {
i n t info;
nod * left;
nod * right;
nod * parent;
};
root
info
left
right
parent
info
left
root
info
right
left
right
parent
info
info
left
right
left
info
right
left
right
info
left
info
left
right
parent
info
right
left
right
info
left
right
(a) Reprezentarea unui arbore binar prin legturi fiu stng i fiu drept
Figur 2
61
(b) Reprezentarea1 unui arbore binar prin legturi fiu stng, fiu drept i printe
Traversari/parcurgeri
ale arborilor
Vor fi prezentate patru modaliti de parcurgere a unui arbore binar (parcurgerea pe niveluri/n
lime i trei parcurgeri n adncime).
11
12
Figur 3
62
N
N
Traversare-BF()
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Algoritmul ncepe prin adugarea rdcinii arborelui n coad (linia 4). La fiecare iteraie a
ciclului while , este scos din coad un nod (cel aflat n coad de cel mai mult timp) pentru afiare
(liniile 6-7). Fiecare fiu nevid al nodului x este apoi adugat n coad (liniile 8-13). Modul de
lucru al unei cozi ne asigur c vom parcurge integral nodurile de pe un nivel nainte de a trece la
nodurile de pe nivelul urmtor.
Traversarea BF poate fi utilizat pentru adugarea unui nod frunz ntr-un arbore binar, astfel
nct s l completm pe niveluri: nu vom insera un nod pe nivelul urmtor, dect dac nivelul
curent este complet. (Arborele binar din imaginea anterioar nu este echilibrat, nu este complet).
Folosim urmtoarele observaii n acest algoritm de inserare.
1. Pentru un arbore binar echilibrat (nlimea oricror doi subarbori cu rdcin pe acelai
nivel difer prin cel mult 1), avem:
j
k
h = log2 (n) ,
unde n este numrul de noduri din arbore.
2. ntr-un abore binar, orice nivel 0 i h complet conine 2i noduri: nivelul 0 ce conine
doar rdcina are 20 = 1 nod, nivelul 1 ce conine cei doi fii ai rdcinii are 21 = 2 noduri,
etc.
3. Asociem nodurilor din arbore indexul lor n parcurgerea BF (rdcinii i corespunde indexul 1, fiului ei stng i corespunde indexul 2, . . ., ultimului nod vizitat i corespunde indexul
n.
Atunci, pentru nodul cu indexul 1 i n, avem c:
a. fiul su stng, dac exist, are indexul 2 i (numr par), iar
b. fiul su drept, dac exist, are indexul 2 i + 1 (numr impar).
Atunci cnd inserm un nod astfel nct s completm pe niveluri arborele binar, inserm al
n + 1-lea nod din arbore, cruia i va corespunde indexul n + 1 n parcurgerea BF.
Noul nod va fi fiul stng sau drept al unui nod cu indexul i. Putem determina care fiu va fi i
indexul i astfel:
a. dac n + 1 este un numr par, atunci va fi fiul stng al nodului cu indexul i i
n+1 = 2i i =
63
n+1
2
n+11
n
=
2
2
Aceasta nseamn c putem afla indexul printelui, apoi s parcurgem pe niveluri arborele
pn la acest index i s legm noul nod de nodul cu acest index. Algoritmul urmtor primete ca
parametru un nod z i l insereaz n arbore, conform strategiei de mai sus.
N
N
Adaug-Frunz-BF(z)
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
Traversarea n adancime
(depth-first) a unui arbore
Exist trei posibiliti pentru traversarea depth-first (DF) a unui arbore binar. Urmtoarele
proceduri recursive de parcurgere, afieaz cheile din noduri n trei ordini diferite, n funcie de
unde este plasat cheia din rdcina x a unui arbore (de rdcin x) fa de cheile din subarborii
stng i drept ai acestuia. Toate cele trei proceduri vor fi apelate prima oar pasnd ca argument
nodul rdcin (root).
Aa cum vedei n imaginea urmtoare, singurul nod din arbore a crui legtur spre printe
va fi NIL este rdcina.
Pentru arborele din imaginea anterioar:
parcurgerea n preordine (RSD) produce secvena:
[7; 3; 8; 6; 5; 9; 12; 1; 4; 11; 2]
64
N
N
Traversare-Preordine(x)
1.
2.
3.
4.
5.
N
N
Traversare-Inordine(x)
1.
2.
3.
4.
5.
i f x , NIL then
Afieaz x->info
TraversarePreordine(x->left)
TraversarePreordine(x->right)
endif
i f x , NIL then
TraversarePreordine(x->left)
Afieaz x->info
TraversarePreordine(x->right)
endif
N
N
Traversare-Postordine(x)
1.
2.
3.
4.
5.
65
i f x , NIL then
TraversarePreordine(x->left)
TraversarePreordine(x->right)
Afieaz x->info
endif
Arbori binari de cautare
ntr-un arbore binar de cutare (binary search tree - BST) cheile sunt ntotdeauna memorate astfel
nct s fie satisfcut proprietatea arborelui binar de cutare:
Fie x un nod din arborele binar de cutare. Dac y este un nod din subarborele stng al lui x, atunci
x->info y->info. Dac y este un nod din subarborele drept al lui x, atunci x->info y->info.3
Aceast proprietate se mai numete i invariantul de ordine. Motivul pentru care ea constituie
un invariant este evident: la orice moment ea trebuie ndeplinit/asigurat n arbore (deci nu
variaz). Identificarea invarianilor este important pentru studiul complexitii.
Traversarea n inordine a unui arbore binar de cutare afieaz n ordine cresctoare toate
cheile (valorile nodurilor) din arbore. (Deci, putem folosi aceast tehnic pentru sortare.) Pentru
arborele binar de cutare din imagine parcurgerea n inordine (SRD) produce secvena:
[1; 2; 3; 4; 5; 6; 7; 8; 9; 11; 12]
Vom folosi pentru arborii binari de cutare a doua reprezentare prezentat, ce utilizeaz i
legtura ctre printele unui nod.
11
12
Figur 4
Cautarea
Vom implementa cutarea recursiv. Algoritmul urmtor caut n arborele de rdcin x nodul care
conine cheia k. Dac acesta exista se va returna un pointer ctre el, altfel se va returna NIL . Ca
urmare a proprietii arborilor de cutare tim c:
- dac nodul x conine o cheie (x->info) mai mic dect k, atunci, dac exist n arbore nodul
cu cheia k, el se va afla sigur n subarborele drept al lui x (liniile 6-7).
- dac nodul x conine o cheie (x->info) mai mare dect k, atunci, dac exist n arbore
nodul cu cheia k, el se va afla sigur n subarborele stng al lui x (liniile 4-5).
Evident, dac x->info este chiar k, atunci cutarea s-a terminat (liniile 1-2). Dac algoritmul
conduce cutarea pe un fiu vid al lui x, atunci prin condiia de la linia 1, la intrarea n procedur,
se va returna NIL i algoritmul se termin.
Iniial, algoritmul se va apela cu argumentul x=root.
3 n funcie de cum definim aceast proprietate, cu inegaliti stricte sau nestricte, arborele binar
de cutare va fi strict, strict la dreapta, strict la stnga sau nestrict. n acest laborator vom lucra cu
arbori binari de cutare strici.
66
N
N
CautRecursiv(x, k)
1.
2.
3.
4.
5.
6.
7.
8.
recursive search
Putem transforma algoritmul ntr-unul iterativ prin introducerea unui ciclu while .
N
N
CautIterativ(x, k)
1.
2.
3.
4.
5.
6.
7.
8.
67
N
N
Minim(x)
1.
2.
3.
4.
N
N
Maxim(x)
1.
2.
3.
4.
Determinarea succcesorului
Pentru operaia de tergere vom avea nevoie s nlocuim nodul ters cu un nod rmas din arbore
astfel nct proprietatea arborelui binar de cutare s fie pstrat. Mai exact, n locul su va fi
plasat acel nod ce conine cea mai mic cheie ce este mai mare dect cea a nodului ters. Cu alte
cuvinte nlocuim un nod x cu nodul y, pentru care avem:
y->info = min{z->info > x->info}, z T.
Un asemenea nod y se numete succesorul lui x.
Pentru gsirea succesorului putem utiliza urmtorul algoritm.
N
N
Succesor(x)
1.
2.
3.
4.
5.
6.
7.
8.
9.
68
successor
Inserarea
Operaia de inserare, ca i tergerea, modific mulimea de chei reprezentat prin arbore. Trebuie
s ne asigurm c, dup inserare, proprietatea arborelui de cutare a fost conservat.
Algoritmul urmtor insereaz nodul z n arborele T.
N
N
Insereaz(T , z)
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
69
y NIL
x
T->root
while x , NIL do
y x
i f z->info < x->info then
x x->left
else
x x->right
endif
endwhile
z->parent y
i f y = NIL then
T->root z
else
i f z->info < y->info then
y->left z
else
y->right z
endif
endif
Deoarece procedura
Insereaz(T,z) primete ca
argument un nod, pentru
inserarea unei chei, putei:
a) s modificai procedura
astfel nct s primeasc
valoarea de inserat (val,
de acelai tip de date ca
info) i s creai i
iniializai nodul la
intrarea n procedur,
sau
b) s scriei o procedur
separat care creeaz i
iniializeaz nodul nou,
dup care apeleaz
Insereaz(T,z) cu acest
nod.
insertion
n prima faz trebuie s gsim locul potrivit pentru nodul nou. Liniile 1-10 identific printele
y al noului nod. Pentru a-l gsi pe y se face o parcurgere n adncime, innd cont de proprietatea
arborelui de cutare, pn se gsete un nod terminal x. Printele acestui nod este referit de y. Parcurgerea efectuat este de fapt cutarea cheii din noul nod, deci vom gsi locul n care aceasta ar
trebui s se afle. A doua faz se concentreaz pe legarea noului nod de arbore. Noul nod trebuie s
conin o referin ctre printele su (prima legtur), iar printele trebuie s conin o referin
ctre noul su fiu (a doua legtur). Linia 11 realizeaz prima legtur, iar liniile 12-20 plaseaz
noul nod, z, ca fiu al lui y n locul corespunztor (a doua legtur). Linia 13 reprezint cazul n
care T este chiar arborele vid i atunci noul nod va deveni chiar rdcina acestuia.
Stergerea
Pentru tergerea unui nod z dintr-un arbore binar de cutare T cu rdcina T->root, putem avea
trei situaii:
i. dac z este o frunz (nu are niciun fiu), atunci eliminm nodul z:
fie prin (z->parent)->left NIL , dac (z->parent)->left = z (z era fiu stng),
fie prin (z->parent)->right NIL , dac (z->parent)->right = z (z era fiu
drept)
ii. dac z are un singur fiu, atunci acel fiu va fi ridicat n locul su. S spunem c x reine
fiul nevid al lui z (fie z->left, fie z->right). Atunci eliminarea i implicit ridicarea se
realizeaz:
fie prin (z->parent)->left x, dac (z->parent)->left = z (z era fiu stng),
fie prin (z->parent)->right x, dac (z->parent)->right = z (z era fiu drept)
iii. dac z are ambii fii nevizi, atunci n locul lui z va fi plasat y, succesorul lui z4 . Pentru
aceasta, practic l tergem pe y din subarborele drept al lui z (nu se poate afla dect n
subarborele drept) i tot subarborele drept al lui z rmas devine subarborele drept al lui y,
respectiv subarborele stng al lui z (pe care nu l modificm) devine subarborele stng al
lui y. Nodul y poate fi chiar z->right.
4 ntr-un arbore binar de cutare succesorul unui nod nu are fiu stng, iar predecesorul unui nod
nu are fiu drept. Altfel, acel fiu ar fi fost chiar el succesorul, respectiv predecesorul.
70
Practic, putem trata cazul i. mpreun cu ii.. Dac z nu are fiu stng, atunci z va fi nlocuit de
fiul drept. Dac fiul drept este i el vid (cazul i.), atunci automat atribuim NIL , aa cum trebuia.
Mai jos, figura 5(a) conine aceast situaie, iar figura 5(b) conine situaia simetric, atunci cnd
z nu are fiu drept i este nlocuit de fiul stng.
NIL
NIL
Rmne tratarea cazului iii. Gsim succesorul y al lui z. Trebuie s l eliminm pe y de la locul
lui i s l aducem n locul lui z:
dac y=z->right, atunci z este nlocuit de y (situaia este ilustrat n figura 6),
NIL
Figur 6
z
r
Figur 7
71
y
r
NIL
y
NIL
N
N
Transplanteaz(T , u, v)
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
N
N
terge(T , z)
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
72
Ca i n cazul inserrii,
urmtoarele proceduri primesc
ca parametru un pointer ctre
nodul z, ce trebuie ters, nu
cheia z->info.
N
N
terge-2(T , z)
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
73
Arbori binari de cautare
indexati
Definitie: Un arbore binar de cutare indexat este un arbore binar de cutare, n care fiecare
nod are un cmp suplimentar, numit leftSize, n care se reine numrul de descendeni din
subarborele stng.
Prin urmare nodul corespunztor acestui tip de arbore se poate implementa n C++ folosind
urmtorul tip structurat:
s t r u c t nod {
i n t info;
nod * left;
nod * right;
i n t leftSize;
};
Un exemplu de arbore binar de cutare indexat este n figura 8(a).
Indexul unui element este poziia sa la traversarea n inordine (SRD) a arborelui cu rdcina n
acel element. Pentru arborele de mai sus, traversarea n inordine este dat de secvena urmtoare:
[2,6,7,8,10,15,18,20,25,30,35,40]
Indexul fiecrui element este atunci cel din tabelul de mai jos.
nod x
index(x)
2
0
6
1
7
2
8
3
10
4
15
5
18
6
20
7
25
8
30
9
35
10
40
11
Observm c x->leftSize == index(x), relativ la elementele din subarborele stng (ce are
rdcina n nodul x). Spre exemplu, pentru nodul 20 (x->info=20), care constituie rdcina ntregului arbore (corespunztor parcurgerii n inordine de mai sus), leftSize este 7, adic exact
index(20). Considerm acum subarborele cu rdcina n nodul cu x->info = 6 (cel ce conine
nodurile 2, 8 i 7). Parcurgerea sa n inordine produce: [2, 6, 7, 8]. Prin urmare indexul asociat
nodului 6 este 1, exact valoarea ce va fi reinut n x->leftSize.
Cautarea
unui element cu un anumit index
Se dorete gsirea n arbore a nodului x pentru care index(x)=k. Ca urmare a observaiei anterioare, putem deduce indexul unui nod utiliznd cmpul leftSize.
Pentru gsirea nodului cutat se va aplica recursiv urmtorul algoritm, pornind de la rdcin.
Dac k < x->leftSize, atunci nodul cutat se afl n subarborele stng al lui x pe.poziia k
i se reia algoritmul pentru x->left.
Dac k > x->leftSize, atunci nodul cutat se afl n subarborele drept al lui x pe.poziia k
- x->leftSize - 1 i se reia algoritmul pentru x->right.
74
20|7
9 > 7
20|7
info
18|0
8|1
2|0
7|0
35|0
25|0
7|0
35|0
25|0
18|0
8|1
2|0
30|1
15|0
6|1
30|1
15|0
6|1
40|3
10|4
40|3
10|4
leftSize
20|7
20|7
40|3
10|4
40|3
10|4
1 < 3
30|1
15|0
6|1
30|1
15|0
6|1
1 = 1
2|0
18|0
8|1
25|0
35|0
2|0
7|0
8|1
18|0
25|0
35|0
7|0
Figur 8
Atentie Algoritmul de mai sus funcioneaz n ipoteza c indexarea se face ncepnd cu nodul
x pentru care index(x)=0, aa cum s-a procedat aici.
75
PROBLEME
1.
...........................................................................................................
6.
7.
3.
4.
5.
am
ana
Detalii: Studentii pot obtine un maxim de 13 puncte. Problemele 1-2 si 6 sunt obligatorii. Problemele 35 sunt suplimentare. Problema 7
iar termenul de predare pentru ea este sapt
am
ana
este facultativa,
8 (1923 noiembrie). Un singur student poate rezolva problema facultativa.
76