Sunteți pe pagina 1din 19

am

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.

i importante (de caracterizare) ale arborilor


Proprietat


O mulime de arbori se mai


numete pdure. De fapt, o
pdure este un graf aciclic, care
nu este neaprat conex.

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.

Singurul nod din arbore fr


printe este rdcina.

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

ntr-un arbore, oricare dou


noduri sunt conectate printr-un
drum elementar unic.

nivel 0

n
alt
imea h = 4

11

12

nivel 1

10

Figur 1

nivel 2

nivel 3

nivel 4

Structurarea unui arbore de nlime h pe h + 1 niveluri

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 arbore care nu conine


niciun nod se numete arbore
vid (T = ) sau arbore nul
(T=NIL ).

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

Reprezentarea arborilor binari


Vom reprezenta arborii binari folosind structuri de date nlnuite. Vor fi prezentate dou metode
de reprezentare. A doua reprezentarea se preteaz pentru a fi extins pentru arbori cu orici fii.
Prima metod de reprezentare
Folosim dou legturi n fiecare nod, left i right, pentru a reine adresa fiului stng, respectiv a fiului drept. Dac un fiu lipsete, adresa sa va fi NIL . Fiecare nod conine i un cmp
de informaie info. n plus, arborele trebuie s dein o referin a rdcinii sale, care pstreaz
numele de root.
Nodul se poate memora n C++ folosind urmtoarea structur:
s t r u c t nod {
i n t info;
nod * left;
nod * right;
};

60

Dei cmpul de informaie al


nodurilor din arbori este n
general numit cheie, vom pstra
denumirea info pentru
liniaritate.

Arborele se poate reine prin:


s t r u c t btree {
nod * root;
i n t height;
i n t size;
};
Observai c putem reine i cmpuri adiionale, care ne ofer informaii suplimentare despre
arbore, n tipul structurat ce descrie arborele. n acest caz pstrm n cmpul height nlimea
arborelui spre rdcina cruia pointeaz root. Cmpul size reine numrul de noduri din arbore,
notat i n.
A doua metod de reprezentare
A doua metod de reprezentare, reine i legturi de la fii la printele lor. Deci putem cunoate
printele unui nod din arbore fr a reine pointeri de traversare suplimentari. Atunci cnd operaiile de baz (inserare, tergere, cutare, accesare) pe un arbore utilizeaz des referine la printele
unui nod i, mai mult, cnd aflarea acestuia nu este la ndemn (nu se poate face simultan), este
indicat s facem un compromis la nivel de spaiu de memorie pentru a obine un timp de execuie mai rapid pentru aceste operaii (sau pentru a accesa mai rapid printele sau pentru a scurta
codul).

Situaia este similar


introducerii legturii previous
la listele dublu nlnuite, cnd
nu mai era necesar un pointer
anterior pentru a obine
precedentul unui nod.

Nodul se poate memora n C++ folosind urmtoarea structur:


Aceast reprezentare poate fi
generalizat pentru arbori cu
un numr k de fii n modul
urmtor. Orice nod reine:

s t r u c t nod {
i n t info;
nod * left;
nod * right;
nod * parent;
};

root

a. adresa printelui su,


b. adresa primului su fiu
(cel mai din stnga) i
c. adresa fratelui su
(nodul cu acelai printe
aflat imediat n dreapta
sa).

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

Cele dou metode de reprezentare a unui arbore binar


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

Un exemplu de arbore binar

ime/pe niveluri (breadth-first) a unui arbore


Traversarea n lat
Parcurgerea breadth-first (BF) viziteaz toate nodurile de pe un nivel de la stnga la dreapta,
apoi trece la nivelul urmtor (primul nivel vizitat este 0).
Pentru arborele din imagine, parcurgerea BF produce secvena:
[7; 3; 4; 8; 12; 11; 2; 6; 5; 1; 9]
Algoritmul utilizeaz o structur de coad Q. Funcia push de inserare n coad difer de cea
prezentat n laboratorul 4 prin faptul c de aceast dat inserm variabile de tipul nodului din
arbore i nu valori ntregi. Deci tipul cmpului info al unui nod din coada Q trebuie s fie pointer
la un nod din arbore.
Deci, dac un nod din arbore este de tipul nod, iar un pointer la un astfel de nod este de tipul
nod *, atunci un element din coada Q va fi de tipul:
s t r u c t nodQ {
nod * info;
nod * next;
};

62

N
N

Traversare-BF()

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.

i f root = NIL then


return
endif
push(Q, root)
while Q , do
pop(Q, x)
Afieaz x->info
i f x->left , NIL then
push(Q, x->left)
endif
i f x->right , NIL then
push(Q, x->right)
endif
endwhile

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

Orice arbore binar complet este


echilibrat.

b. dac n + 1 este un numr impar, atunci va fi fiul drept al nodului cu indexul ii


n+1 = 2i +1 i =

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.

i f n+1 par then


n+1
i
2
else
n
i
2
endif
contor 0
i f root , NIL then
push(Q, root)
while (Q , ) and (c i) do
pop(Q, x)
c c + 1
i f x->left , NIL then
push(Q, x->left)
endif
i f x->right , NIL then
push(Q, x->right)
endif
endwhile
endif
i f contor = 0 then
root z
else
i f n+1 par then
x->left z
else
x->right z
endif
endif

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

La implementarea n C++ (nu


numai) liniile 1-5 pot fi
nlocuite cu:
n + 12
i
.
2

parcurgerea n inordine (SRD) produce secvena:


[6; 8; 9; 5; 3; 12; 1; 7; 11; 4; 2]
parcurgerea n postordine (SDR) produce secvena:
[6; 9; 5; 8; 1; 12; 3; 11; 2; 4; 7]
Observai c n toate trei parcurgerile, cheile din subarborele stng sunt afiate naintea cheilor
din subarborele drept.


Parcurgerea n preordine (RSD)

N
N

Traversare-Preordine(x)
1.
2.
3.
4.
5.

Parcurgerea n inordine (SRD)

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

Parcurgerea n postordine (SDR)

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

Structura unui arbore binar de cutare

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 acest laborator lucrm n


ipoteza c nu exist chei
multiple (k apare cel mult o
dat).

N
N

CautRecursiv(x, k)
1.
2.
3.
4.
5.
6.
7.
8.

i f x = NIL OR k = x->info then


return x
endif
i f k < x->info then
return Caut-Recursiv(x->left , k)
else
return Caut-Recursiv(x->right , k)
endif

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

while x , NIL AND k , x->info do


i f k < x->info then
x x->left
else
x x->right
endif
endwhile
return x

Determinarea minimului si a maximului


Observm c nodul cu cheia minim este obinut dac parcurgem arborele pornind din rdcin i
folosind doar legtura ctre fiul stng. Simetric, maximul se obine printr-o traversare ce utilizeaz
doar legtura ctre fiul drept. Aceasta se datoreaz proprietii arborelui binar de cutare.
Procedurile urmtoare returneaz un pointer ctre elementul cu cheia minim, respectiv elementul cu cheia maxim din arbore.

N
N

Minim(x)
1.
2.
3.
4.

while x->left , NIL do


x x->left
endwhile
return x

N
N

Maxim(x)
1.
2.
3.
4.

while x->right , NIL do


x x->right
endwhile
return x

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

i f x->right , NIL then


return Minim(x->right)
endif
y x->parent
while (y , NIL) and (x = y->right) do
x y
y y->parent
endwhile
return y

Similar, predecesorul unui nod


x este nodul y cu cea mai mare
cheie care este mai mic dect
cea a nodului x. Adic:
y->info = max{z->info <
x->info}, z T.

successor

Dac un nod x deine un fiu


drept, x->right, atunci
succesorul su va fi cheia
minim din subarborele de
rdcin x->right. n caz
contrar, (fiul drept, x->right,
este vid), succesorul y va fi
strmoul aflat la cea mai mic
adncime al lui x care are un fiu
stng, y->left, ce este de
asemenea strmo al lui x.

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

(a) Cazul cnd z nu are fiu stng

(b) Cazul cnd z nu are fiu drept

1Figur 5 Cazurile i. i ii. tratate concomitent


1

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

Cazul cnd succesorul este chiar fiul drept al nodului z

Figur 6

altfel, l nlocuim pe y cu fiul su drept i apoi l nlocuim pe z cu y (situaia este ilustrat


1
n figura 7).

z
r

Cazul cnd succesorul nu este fiul drept al nodului z


1

Figur 7

71

y
r

NIL

y
NIL

Obinem astfel 4 cazuri ce se vor regsi n algoritmul de tergere.


Utilizm urmtoarea procedur, numit Transplanteaz(T, u, v), pentru nlocuirea subarborelui de rdcin u cu subarborele de rdcin v: v devine fiul (stng sau drept) al printelui lui
u.

N
N

Transplanteaz(T , u, v)

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

i f u->parent = NIL then


T->root = v
else
i f u = (u->parent)->left then
(u->parent)->left v
else
(u->parent)->right v
endif
endif
i f v , NIL then
v->parent u->parent
endif

n continuare avei pseudocodul pentru abordarea prezentat.

N
N

terge(T , z)

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.

72

i f z->left = NIL then


Transplanteaz(T, z, z->right)
else
i f z->right = NIL then
Transplanteaz(T, z, z->left)
else
y Minim(z->right)
i f y->parent , z
Transplanteaz(T, y, y->right)
y->right z->right
(y->right)->parent y
endif
Transplanteaz(T, z, y)
y->left z->left
(y->left)->parent y
endif
endif

Ca i n cazul inserrii,
urmtoarele proceduri primesc
ca parametru un pointer ctre
nodul z, ce trebuie ters, nu
cheia z->info.

De ce este corect s folosim


apelul Minim(z->right) (linia
7) pentru gsirea succesorului
lui y?

Alt procedur pentru tergere


Alternativ, putem utiliza urmtoarea procedur de tergere care trateaz cazurile i., ii. i iii.
Dac suntem n cazul i. (z nu are fii, atunci printele lui z va reine NIL n locul legturii
ctre z. Dac are un singur fiu (cazul ii.), acesta este preluat ca fiu, pe poziia corespunztoare, de
printele lui z. n fine, dac ambii fii sunt nevizi, este gsit succesorul y care va fi eliminat i l va
nlocui pe z.

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

i f (z->left = NIL) or (z->right = NIL) then


y z
else
y Succesor(z)
endif
i f y->left , NIL then
x y->left
else
x y->right
endif
i f x , NIL then
x->parent y->parent
endif
i f y->parent = NIL then
T->root x
else
i f y = (y->parent)->left then
(y->parent)->left x
else
(y->parent)->right x
endif
endif
i f y , z then
z->info y->info
endif
return y

Urmrii algoritmul i depistai


cum se realizeaz tratarea
cazurilor, deoarece ele sunt
organizate diferit.


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 este x.

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

(a) Cutm nodul x cu index(x)=9 n arbore.


Avem deci
1 k=9.

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

(b) Primul nod verificat va fi 20, rdcina. Ne


aflm n cazul 3, cnd
1 k > x->leftSize, deoarece k=9>7, unde 7 este valoarea cmpului
lef tSize a nodului 20. Prin urmare, continum pe
subarborele drept al lui 20 i vrem s gsim nodul de la poziia k - x->leftSize - 1 = 9 - 7
- 1 = 1. Fiul drept al lui 20 este 40.

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

(c) Nodul 40 are leftSize=3, deci este strict mai


mare dect k=1.Ne aflm
1 n cazul 2. Continum
s cutm nodul de la poziia k=1 n subarborele
stng al lui 40, a crui rdcin este 30.

Figur 8

(d) Obinem cazul 1, cnd k=x->leftSize, deoarece 30 reine n cmpul


1 leftSize valoarea 1,
exact valoarea cutat. Algoritmul se ncheie.

Exemplu de cutare ntr-un arbore binar de cutare indexat

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.

........................................................................................................... 

(2p) S se implementeze o structur de arbore binar cu


cheile numere ntregi, inserate pe niveluri. Scriei funcii pentru:

6.

(1p) S se ordoneze descresctor un ir de cuvinte citite


de la tastatur, folosind un arbore binar de cutare.

7.

(10ps) Zece haiduci au dat peste o comoar de 50 de


galbeni. Ei vor sa mpart banii dup urmtorul sistem:

a. Augarea unui nod frunz;


b. Parcurgerea cheilor conform strategiei RSD (preordine);
c. Parcurgerea cheilor conform strategiei SRD (inordine);
d. Parcurgerea cheilor conform strategiei SDR (postordine);
2.

(5p) S se implementeze un arbore binar de cutare cu


urmtoarele operaii:
a. insert(root,x) insereaz cheia x n arborele de
rdcin root;
b. search(root,x) returneaz 1 dac elementul x se
afl n arborele de rdcin root i 0 n caz contrar;
c. findMax(root) returneaz elementul maxim din
arborele de rdcin root, fr a-l terge din arbore;
d. delete(root,x) terge nodul cu cheia x din arborele de rdcin root (pstrnd proprietatea de arbore binar de cutare);

3.
4.

5.

(1p) S se utilizeze un arbore binar de cutare pentru


sortarea a n numere.
(2p) Dat un arbore binar de cutare i doi ntregi k1 i
k2 , s se afieze toate cheile x din arbore care au proprietatea: k1 x k2 .
(3p) S se scrie un algoritm pentru afiarea elementului de pe poziia k (n ordinea cresctoare a elementelor
dintr-un ir), folosind un arbore binar de cutare indexat.

(a) cel mai btrn haiduc propune o schem de distribuire a monedelor;


(b) haiducii voteaz dac sunt de acord cu aceast
schem; spunem c haiducii sunt de acord cu schema
atunci cnd majoritatea voteaz n favoarea acesteia.
n cazul n care sunt voturi egale pro i contra, atunci
schema este adoptat;
(c) dac haiducii sunt de acord cu schema, atunci banii se
mpart conform propunerii; dac nu, atunci haiducul
care a fcut propunerea este ucis, i urmtorul cel mai
btrn haiduc face o nou propunere.
Fiecare haiduc i bazeaz deciziile pe urmtoarele considerente:
(a) vrea s supravieuiasc;
(b) vrea s maximizeze suma care i revine n urma mpririi;
(c) nu are ncredere n ceilali haiduci, aa c nu sunt posibile aranjamente ntre ei pentru a mpri banii.
Numerotnd haiducii cu H10; H9;... ; H1 (unde H10
este cel mai btrn haiduc, iar H1 cel mai tnr), s se
spun care este schema de mprire a monedelor.


am
ana

9 (2630 noiembrie 2012) inclusiv.


 Termen de predare: Sapt

 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

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