Sunteți pe pagina 1din 10

Tehnici de Programare Udritoiu Stefan

9. Arbori Stoica Spahiu Cosmin


1

Lucrarea 9 Structuri arborescente.


Introducere
Dac# ne-am uitat la un arbore genealogic, sau la o ierarhie de comand# ntr-o firm#,
am observat informa&iile aranjate ntr-un arbore.
Un arbore este compus dintr-o colec&ie de noduri, unde fiecare nod are asociat# o
anumit# informa&ie i o colec&ie de copii.
Copiii unui nod sunt acele noduri care urmeaz# imediat sub nodul ns#i.
Printele unui nod este acel nod care se afl# imediat deasupra.
R#d#cina unui arbore este acel nod unic, care nu are nici un p#rinte.

Exemplu de ierarhie de comand# intr-o firm#:

In acest exemplu r#d#cina arborelui este Bob Smith. Este r#d#cin# deoarece nu are
nici un p#rinte. Copilul s#u direct este Tina Jones.
Tina Jones are 3 noduri copii (nodurile de pe nivelul urm#tor din ierarhie): Jisun Lee,
Frank Mitchell i Davis Johnson. P#rintele s#u este Bob Smith (nodul de pe nivelul superior,
din ierarhie).
To&i arborii au urm#toarele propriet#&i:
Exist# o singur# r#d#cin#
Toate nodurile, cu excep&ia r#d#cinii, au exact un singur p#rinte
Nu exist# cicluri. Aceasta nseamn# c# pornind de la un anumit nod, nu exist#
un anumit traseu pe care l putem parcurge, astfel nct s# ajungem napoi la nodul
de plecare.



Arbori Binari
Arborii binari sunt un tip aparte de arbori, n care fiecare nod are maxim 2 copii.
Pentru un nod dat, ntr-un arbore binar, vom avea copilul din stnga, i copilul din dreapta.
Exemplu de arbori binari:
PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
2

Arborele din figura a) are 8 noduri, nodul 1 fiind r#d#cina. Acesta are ca i copil
stnga nodul nr.2, iar ca i copil dreapta nodul nr.3. La rndul s#u nodul nr.2 nu are dect un
singur copil (stnga), i anume nodul nr 4.
Deci un nod dintr-un arbore binar poate avea 2 copii (stnga i dreapta), un singur
copil (doar stnga sau doar dreapta) sau nici unul (exemplu nodul 8).
Nodurile care nu au nici un copil se numesc noduri frunz#.
Nodurile care au 1 sau 2 copii se numesc noduri interne.

Pentru re&inerea informa&iei n calculator se va folosi alocarea dinamic#. Deoarece
pentru fiecare nod n parte este necesar s# se re&in#, pe lng# informa&ia util# i leg#turile cu
nodurile copii (adresele acestora), ne putem imagina urm#toarea structura a unui nod:

struct Nod {
int inf;
Nod *leg_st;
Nod *leg_dr;
};
Nod *prim;

unde: leg_st reprezint# adresa nodului copil din stnga, inf reprezint# cmpul cu
informa&ie util#, iar leg_dr este leg#tura cu copilul din dreapta.
Un arbore binar va avea urm#toarea structur# intern#:

adr1 nivel 1



adr2 adr3 nivel 2



adr5 nivel 3

Pe nivelul 1 vom avea un singur nod, nodul r#d#cin#. Componenta leg_st va fi egal#
cu adresa adr2, nodul din stnga de pe nivelul 2, iar componenta leg_dr va fi egal# cu adresa
adr3.
Componentele leg_st i leg_dr ale nodului din stnga de pe nivelul 2, vor fi egale cu
adr4, respectiv adr5.
leg_st inf leg_dr
leg_st inf leg_dr
leg_st inf leg_dr leg_st inf leg_dr
leg_st inf leg_dr leg_st inf leg_dr
PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
3
Nodul din dreapta de pe nivelul 2 nu mai are nici un copil i de aceea componentele
sale leg_st i leg_dr vor avea valoarea NULL (ca i la liste dinamice).
n mod analog i componentele leg_st i leg_dr ale nodurilor de pe nivelul 3 vor avea
valoarea NULL.


Arbori Binari de Cutare
Un arbore binar de c#utare este un arbore binar destinat mbun#t#&irii timpului de
cutarea informa&iei. El va trebui s# respecte urm#toarea proprietate: pentru oricare nod n,
fiecare din descendentii din subarborele din stnga va avea valoarea informa&iei mai mic#
dect a nodului n, iar fiecare din descenden&ii din subarborele din dreapta va avea valoarea
informa&iei mai mare dect a nodului n.

Exemplu:


n figura de mai sus avem 2 arbori binari.
Arborele din figura b) este arbore binar de c#utare deoarece este respectat# regula de
mai sus, si anume c# n oricare subarbore stng valorile trebuie s# fie mai mici dect ale
r#d#cinii i n oricare subarbore dreapta, valorile trebuie s# fie mai mari dect ale r#d#cinii.
(Cu alte cuvinte, toate valorile din nodurile aflate n stnga nodului n trebuie s# fie mai mici,
iar cele din dreapta mai mari).
Se folosete exprimarea oricare din subarborii stng respectiv drept, deoarece
pentru r#d#cina 7, elementele subarborelui stng sunt 3, 1, 5, 4 (care sunt toate mai mici
dect 7), iar elementele subarborelui drept sunt 11, 10, 15 (care sunt toate mai mari dect 7).
Dac# n schimb vom considera ca r#d#cin# nodul 3, vom avea ca subarbore stng nodul 1 (1
este mai mic dect 3), iar ca subarbore drept nodurile 5 i 4 (ambele mai mari dect 3).
Dac# vom considera ca i r#d#cin# pe nodul 10, acesta nu are nici un copil, deci
implicit respect# regula pentru arborii binari de c#utare.
Arborele din figura a) nu este un arbore binar de c#utare deoarece nu toate nodurile
respect# regula.
Nodul 4 nu are ce c#uta acolo n dreapta nodului 8. Ar trebui s# se afle n stnga lui 8
(4<8). Dac# privim mai sus observ#m c# nodul 4 ar trebui s# se afle i in stnga nodului 10,
i n stnga nodului 9, i n stnga nodului 7. Cu alte cuvinte nodul 4 nu are ce c#uta n
subarborele drept. Unde ar trebui s# fie pozi&ionat astfel nct i arborele din figura a) s# fie
arbore binar de c#utare?



PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
4
Crearea #i inserarea ntr-un arbore binar de cutare
























Vom considera arborele din dreapta. S#
presupunem c# dorim s# inser#m nodul cu
valoarea 62. Acesta se va insera ca nod frunz#.
Pentru a-l insera va trebui s# c#ut#m o
pozi&ie n arbore care respect# regula de
integritatea a arborilor binari de c#utare.




Vom ncepe prin compararea nodului de
inserat (62), cu r#d#cina arborelui (90).
Observ#m c# este mai mic dect ea, deci va
trebui inserat undeva n subarborele stng al
acesteia.






Vom compara apoi 62 cu 50. Din moment
ce 62 este mai mare dect 50, nodul 62 va trebui
plasat undeva n subarborele drept al lui 50.







Se compar# apoi 62 cu 75. Deoarece 75
este mai mare dect 62, 62 trebuie s# se afle n
subarborele din stnga al nodului 75





Dar 75 nu are nici un copil n partea stng#.
Asta nseamn# c# am g#sit loca&ia pentru nodul 62.
Tot ceea ce mai trebuie f#cut este s# modific#m n
nodul 75 adresa c#tre copilul din stnga, nct s#
indice spre 62.
PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
5
Prin crearea unui arbore binar de c#utare (A.B.C.) vom n&elege de fapt crearea
r#d#cinii, restul nodurilor fiind ad#ugate prin opera&ia de inserare.
Implementare :

//programul va primi ca parametru numrul pe care trebuie s l adauge
void insertie(int nr)
{
Nod *nod1, *nod2, *nod3;


//se creaz nodul care se adaug n arbore.
nod1 = new Nod;
nod1->inf = nr;
//deoarece o s se adauge ca nod frunz, el nu va avea nici un copil, deci
legturile stnga #i dreapta, vor fi nule
nod1->leg_st = NULL;
nod1->leg_dr = NULL;
//verificam mai intai dac exist o rdcin (dac arborele a fost creat)
if(prim==NULL)
{
//nodul creat va deveni rdcina arborelui
prim = nod1;
}
//dac exist un nod rdcin, inserarea n arbore se va face conform
algoritmului prezentat mai sus.
else
{
nod2 = prim;
//se va cuta locul de inserare al nodului nod1, pornind cutarea din
rdcin. Nodul nod3 va reprezenta nodul printe al nodului nod1
while (nod2 != NULL) {
if (nr < nod2->inf) {
nod3 = nod2;
nod2 = nod2->leg_st;
}//end if
else { // se merge spre dreapta
nod3 = nod2;
nod2 = nod2->leg_dr;
}//end else
}//end while
//dup gsirea nodului printe, se creaz legtura nod3 (nod printe) ->
nod1 (nodul inserat acum)
if (nr < nod2->inf)
//se asaza in stnga printelui
nod3->leg_st = nod1;
else
//se a#az n dreapta printelui
nod3->leg_dr = nod1;
}//end else
return t;
}


Parcurgerea unui Arbore (Listarea)

Exist# 3 tipuri de parcurgere a unui arbore: inordine, preordine i post ordine.
Aceste denumiri corespund modului cum este vizitat# r#d#cina.
Parcurgerea n preordine:
PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
6
Parcurgerea n inordine se bazeaz# pe urm#torul principiu: se va vizita mai nti r#d#cina,
copilul (copiii) din stnga, iar apoi copilul (copiii) din dreapta.
Implementarea se va face recursiv, astfel nct nu ne intereseaz# ce se ntmpl# dect pe
unul din nivele (de exemplu pe primul), pe restul procedndu-se identic.
Fie arborele din figur#:


Parcurgerea n preordine presupune:
1. se va vizita rdcina 90
2. se viziteaz# copilul din stnga (50). Dar acesta este la rndul s#u r#d#cin# pentru
subarborele 20 75. Fiind r#d#cin#, ea se viziteaz# prima. Deci vizit#m i nodul 50.
3. se viziteaz# copilul din stnga al nodului r#d#cin# 50, adic# nodul 20. Si acesta este
r#d#cin# pentru subarborele 5 25. Fiind r#d#cin#, se va vizita i nodul 20.
4. se viziteaz# copilul din stnga al r#d#cinii 20, adic# nodul 5. Si acesta este r#d#cin#
pentru arborele vid. Il vizit#m.
5. cum pe ramura aceasta nu mai avem ce vizita, ne ntoarcem la r#d#cina 20. Aceasta este
deja vizitat#. La fel i copilul din stnga. Vom vizita copilul din dreapta, nodul 25.
6. nodul 25 nu mai are copii, deci nu mai avem ce vizita sub el. Cum pentru nodul r#d#cin#
20 am vizitat si copilul din stnga i copilul din dreapta, vom mai urca un nivel la nodul
r#d#cin# 50. Pentru acesta tocmai am terminat de vizitat subarborele stng. Mai avem de
vizitat subarborele drept. Vom merge la nodul 75. Nodul 75 este r#d#cin# pentru un alt
subarbore. l vizit#m.
7. mergem la copilul din stnga, nodul 66.
8. cum nodul 66 nu mai are copii, revenim la r#d#cina 75, pentru care vom vizita copilul din
dreapta: nodul 80
9. pentru r#d#cina 75 am vizitat tot ce se putea. Urc#m la r#d#cina 50. Si pentru aceasta am
vizitat tot ce se putea. Urc#m la r#d#cina 90. Aici tocmai am terminat de vizitat
subarborele stng. Mai avem de vizitat subarborele drept. Vom merge la nodul 150. El
este r#d#cin# pentru subarborele 95 175, deci l vizit#m
10. vizit#m copilul s#u din stnga, 95
11. Ne ntoarcem la r#d#cina 150. Vizit#m copilul din dreapta, 175
12. ne ntoarcem la r#d#cina 90, pentru care am terminat de vizitat si subarborele drept. Cum
nu mai exist# nici un nivel deasupra sa, am terminat de vizitat tot arborelel.

Vizitarea arborelui va ntoarce vectorul:
90 50 20 5 25 75 66 80 150 95 175

Dei la prima vedere pare destul de complicat, implementarea este destul de simpl#. Se va
folosi o func&ie Preordine care primete ca parametru ini&ial r#d#cina arborelui (respectiv,
prin apel#ri succesive, r#d#cinile subarborilor)

void Preordine(Nod* rad)
{
PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
7
//dac nu s-a ajuns la ultimul nod
if (rad != NULL) {
//se viziteaz rdcina
printf( %d - ,rad->inf);
// se viziteaz copilul din stnga, apoi cel din dreapta
Preordine(rad->leg_st);
Preordine(rad->leg_dr);
}
}

Parcurgerea n inordine
Parcurgerea n inordine presupune vizitarea mai nti a copilului din stnga, apoi vizitarea
r#d#cinii i mai apoi a copilului din dreapta.
Pentru arborele anterior, se procedeaz# astfel:
1. se pornete de la r#d#cina 90. Pentru aceasta se viziteaz# mai nti copilul din stnga,
nodul 50. Si acesta este la rndul lui o r#d#cin# pentru arborele 20 - 75. De aceea vom
vizita mai intai copilul s#u stng, nodul 20, care la rndul s#u este r#d#cin# pentru
arborele 5 25. Vom vizita mai nti copilul stng, nodul 5.
2. pentru nodul 5 nu mai avem ce vizita. Revenim la rdcina 20, pentru care tocmai am
vizitat subarborele stng. Conform defini&iei, o vizit#m pe ea.
3. vizit#m nodul 25, copilul s#u drept.
4. revenim la r#d#cina 20. Nu mai avem ce vizita pe acest nivel. Urc#m la rdcina 50.
Pentru aceasta am vizitat subarborele stng. Este rndul ei s# o vizit#m.
5. Vom vizita apoi subarborele ei drept, dup# modelul anterior
..

n final vom ob&ine parcuregerea:
5 20 25 50 66 75 80 90 92 95 111 150 166 175 200
Se observ# faptul c# parcurgerea n inordine va afia de fapt vectorul ordonat cresc#tor.

void Inordine(Nod* rad)
{
//dac nu s-a ajuns la ultimul nod
if (rad != NULL) {
// se viziteaz copilul din stnga
Inordine(rad->leg_st);
//se viziteaz rdcina
printf( %d - ,rad->inf);
//se viziteaz copilul din dreapta
Inordine(rad->leg_dr);
}
}

Parcurgerea n postordine
Pentru parcurgerea n postordine, se va vizita mai nti subarborele stng, apoi
subarborele drept i de abia ultima dat# r#d#cina.

Care este vectorul returnat de aceast# parcurgere?
Implementa&i algoritmul!


&tergerea dintr-un arbore binar de cutare

Ideea de baz# pentru tergerea dintr-un arbore astfel nct s# se p#streze structura de
arbore binar de c#utare este s# nlocuim nodul care se dorete s# se tearg# cu cel mai din
PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
8
stnga nod, al subarborelui drept al nodului de ters.



Prezent#m n continuare implementarea algoritmului de mai sus. Func&ia de tergere va primi
ca parametru informa&ia care dorim s# o tergem (num#rul de ters) i va returna true n cazul
n care a f#cut tergerea sau fals n cazul n care informa&ia care dorim s# o tergem din
arbore, nu a fost g#sit# (dorim s# tergem nodul 1000?).

bool Sterge(int nr)
{
Nod *tmp,*tmp1,*tmp2;
//se porne#te cutarea informa&iei de #ters din rdcin
tmp1 = rad;
while (tmp1->inf != nr)
{
if (tmp1->inf > nr)
tmp1 = tmp1->leg_st;
else
tmp1 = tmp1->leg_dr;
}
tmp = tmp1;
//dac suntem n cazul I
Pentru tergerea unui nod avem
urm#toarele cazuri:

Cazul I
Dorim s# tergem nodul 50.
Acesta nu are subarbore drept, aa c#
l vom nlocui pur simplu cu nodul
20.



Cazul II
Dorim s# tergem nodul 150.
Subarborele drept nu con&ine dect
nodul 175 Nu exist# un subarbore
stng al subarborelui drept.
Se va nlocui nodul 150 cu 175.



Cazul III
Dorim s# tergem nodul 50.
Deoarece subarborele drept al
nodului 50 con&ine un subarbore
stng, se va alege cel mai din stnga
nod al subarborelui drept a lui 50.
Acest cel mai din stnga nod va
con&ine cel mai mic numr mai mare
dect nodul de #ters. In cazul nostru
acest nod este 66.
PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
9
if (tmp1->leg_dr==NULL){
//mutare inf din nodul din st, in nodul curent
tmp1->inf=tmp1->leg_st->inf;
//refacere legturi
tmp1->leg_st = tmp1->leg_st->leg_st;
delete tmp1->leg_st;
}
else
//nu avem copil stnga
if (tmp1->leg_st == NULL){
//mutare inf din nodul din st, in nodul curent
tmp1->inf=tmp1->dr->inf;
tmp1->dr = tmp1->dr->dr;
delete tmp1->dr;
}
//cazul III
else {
//mergem la copilul din dreapta
tmp = tmp1->leg_dr;
tmp2 = tmp1;
//cutm cel mai din stnga copil
while (tmp->leg_st != NULL)
{
tmp2 = tmp;
tmp = tmp->leg_st;
}

tmp1->inf = tmp->inf;
tmp2->leg_st = NULL;
delete tmp;
}//end else

return 0;
}



Probleme propuse

1. Implementa&i opera&iile de ad#ugare, tergere din arbore, c#utare i parcurgere prin toate
trei metodele, folosind doar func&ii recursive. Implementa&i o func&ie de parcurgere care
sa returneze sirul ordonat descresc#tor. (a nu se ordona vectorul dup# ce s-a f#cut
parcurgerea)

2. Implementa&i opera&iile de ad#ugare n arbore (recursiv), tergere din arbore (nodul de
ters se va nlocui cu cel mai din dreapta nod al subarborelui stng al nodului de ters) i
parcurgere Parcurgerea se va face printr-o metod# care s# returneze sirul ordonat
descresc#tor.

3. Implementa&i un arbore unde fiecare nod are maxim 3 copii, aranja&i dup# urm#toarea
regul#:
copilul din stnga este mai mic dect jumatate din nodul r#d#cin# (nod x <
r#d#cin#/2)
nodul din mijloc are informa&ia cuprins# ntre [r#d#cin#/2 si r#d#cin#]
nodul din dreapta are informa&ia > dect informa&ia din r#d#cin#

PDF created with pdfFactory Pro trial version www.pdffactory.com
Tehnici de Programare Udritoiu Stefan
9. Arbori Stoica Spahiu Cosmin
10
4. Eviden&a produselor aflate n stocul unui magazin se &ine ntr-un arbore de c#utare. Pentru
fiecare nod se re&ine: denumire produs, pre&, cantitate. n fiecare sear# arborele este
actualizat prin comenzi de forma:
i se mai introduc produse primite de la depozit (Aten&ie: un astfel de produs este
posibil s# se mai afle n stoc)
s se terg produsele vndute n ziua respectiv#
v se tip#rete valoarea tuturor produselor aflate pe stoc
L se tip#rete o list# cu toate produsele aflate pe stoc

5. Se citesc de la tastatur# n numere naturale care se adaug# pe m#sur# ce se citesc ntr-o
stiv# (implementat# dinamic). S# se adauge aceste numere ntr-un arbore binar de c#utare.

6. Definim un arbore de c#utare pentru numere complexe, n care fiecare nod va con&ine ca
informa&ie util# partea real# i partea imaginar# a unui num#r complex de forma x + iy. S# se
creeze un arbore binar de c#utare care s# memoreze n numere complexe citite de la tastatur#,
apoi s# se scrie o func&ie care s# tearg# din arbore numerele complexe care au partea real# i
partea imaginar# egal#.

7. Un arbore binar de c#utare se numete AVL dac# pentru orice nod, diferen&a dintre
n#l&imea subarborelui stng i a subarborelui drept este -1, 0 sau 1 (n#l&imea reprezint#
num#rul de nivele). S# se construiasc# un arbore AVL care s# aib# n noduri cheile 1, 2, n.
Indica&ie: s# se foloseasc# un algoritm Divide et Impera. La fiecare pas al procedurii
recursive de creare se introduce n arbore un subinterval al mul&imii {1,2 n} cuprins ntre
{stm} iar apoi {m+1, dr}, cu m = (st + dr)/2

8.
PDF created with pdfFactory Pro trial version www.pdffactory.com

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