Sunteți pe pagina 1din 39

14.

ARBORI ECHILIBRAI
14.1 Echilibrarea structurilor arborescente
Pentru a descrie gradul de echilibru al structurilor arborescente sunt definite dou abordri: - arbori perfeci echilibrai n care pentru fiecare nod, diferena dintre numrul de noduri ale subarborelui drept i stng ia valori n mulimea {-1 ; 0 ; +1}; ntr-un arbore perfect echilibrat de nlime h, toate nodurile frunz sunt pe acelai nivel i orice nod de pe nivelurile intermediare 1..h-2 are numrul maxim de fii; de exemplu, figura 14.1 descrie un arbore binar de cutare perfect echilibrat;
23

10

27

18

Figura 14.1 Arbore binar perfect echilibrat cea mai simpl metoda de a obine un astfel de arbore se bazeaz pe parcurgerea prin metoda divide et impera a irului de chei ordonate cresctor i inserarea valorii din mijloc n arbore; aceasta metoda este ineficienta n practic deoarece presupune realizarea unui volum mare de calcule dup fiecare operaie de inserare sau tergere ; efortul ridicat de prelucrare este dat de parcurgerea n inordine a arborelui pentru a obine irul sortat cresctor al cheilor si de reconstrucia structurii ; considernd un arbore binar de cutare, metoda utilizata n acest sens, echilibrareArb, are ca parametrii irul sortat cresctor al valorilor, vectorul chei, dimensiunea acestuia, dim, limitele intervalului curent, stanga, respectiv, dreapta, i rdcina arborelui ce va fi creat; meninerea unei astfel de structuri reprezint o operaie cu grad de complexitate foarte ridicat, fapt care conduce la recrearea arborelui perfect echilibrat dup fiecare operaie de inserare sau tergere cu metoda echilibrareArb;
void echlibrareArbore(int *chei, int dim, int stanga, int dreapta, NodArbore *&radacina){ if (dreapta>=stanga){ int mijloc=(dreapta+stanga)/2; if (dreapta-stanga==1){ radacina =inserareArbore(radacina, chei[stanga]); radacina = inserareArbore (radacina, chei[dreapta]); }

else{ if (dreapta==stanga) radacina = inserareArbore (radacina, chei[stanga]); else{ radacina = inserareArbore (radacina, chei[mijloc]); echlibrareArbore (chei,dim,stanga, mijloc -1, radacina); echlibrareArbore (chei,dim, mijloc +1,dreapta, radacina); } } } }

imperfect echilibrat n care pentru fiecare nod, diferena dintre nlimea subarborelui drept i nlimea subarborelui stng ia valori n mulimea {-1 ; 0 ; +1}; crearea unei astfel de structuri se bazeaz pe utilizarea metodei prezentate anterior pornind de la un set de valori sortate cresctor sau descresctor; meninerea gradului de echilibru al structurii dup operaiile de inserare sau tergere este posibil prin metode cu un grad de complexitate acceptabil i care sunt specifice unor structuri arborescente echilibrate particulare, AVL, arbori B, arbori Rosu & Negru; aceste metode implic un efort de prelucrare mai mic dect volumul operaiilor asociat reconstruciei arborelui prin metoda echilibrareArb.

Structurile arborescente sunt structuri de date dinamice n care elementele sunt poziionate ierarhic n funcie de legtura printe copil ce exist ntre dou elemente. Din punct de vedere al minimizrii efortului de regsire, aceast organizare este mai eficient n raport cu structurile dinamice liniare, deoarece reduce numrul de comparri necesar identificrii unui element. n cazul unei structuri de date liniare, cel mai nefavorabil caz descrie o complexitate egal cu O(m), unde m reprezint numrul de elemente, i este generat de cutarea ultimului element. Aceast situaie este ntlnit i n cazul structurilor arborescente ineficient construite, n care fiecare nod are maxim un fiu i care au asociat imaginea unei liste. Pentru a evita acest lucru i pentru de a beneficia de efectele pozitive ale utilizrii structurilor arborescente n operaiile de cutare se definesc reguli stricte de realizare ale unei astfel de structuri. Prin prisma acestor reguli, structurile arborescente se difereniaz pe mai multe tipuri. Dintre acestea, structurile arborescente echilibrate ocup o pondere ridicat n dezvoltarea de soluii eficiente deoarece descriu un nivel constant de efort apropiat de cel optim. Se consider irul valorilor 23, 10, 27, 18, 3, 2 pe baza crora se definete un arbore binar de cutare. Structura arborescenta obinut este descris n figura 14.2.

23

10

27

18

Figura 14.2 Arbore binar de cutare Din analiza modului in care sunt poziionate valorile, situaia cea mai puin favorabil ce caracterizeaz acest arbore binar de cutare este data de cazul n care nodul ce conine cheia cu valoarea 2 are o frecven ridicat de utilizare. Situaia este generat de faptul ca cel mai lung drum de la nodul rdcin la un nod frunza este dat de drumul 23 10 3 2, de lungime 4. Dimensiunea este determinat de numrul de comparri necesare identificrii nodului cutat. Pe baza unei aranjri echilibrate a valorilor, acelai set de valori este reprezentat de structura arborescenta urmtoare
10

23

18

27

Figura 14.3 Arbore binar de cutare echilibrat Prin prisma cazului cel mai puin favorabil, arborele din figura 14.3 este mai eficient dect cel anterior deoarece numrul maxim de comparri necesare identificrii oricrui nod din structura este egal cu 3. n funcie de numrul de elemente dintr-un arbore binar de cutare, n, o structur echilibrat descrie o complexitate egal cu O(log2n) pentru cel mai nefavorabil caz. n schimb, o structur arborescent de acelai tip, dar care nu este echilibrat, este caracterizat pentru cel mai nefavorabil caz de o complexitate egal cu O(n). Minimizarea efortului de regsire a informaiilor se obine printr-o aranjare echilibrata a valorilor pe ambii subarbori ai fiecrui nod.

14.2 Caracteristici ale arborilor AVL


Un arbore AVL, definit prima dat de G.M. Adelson-Velskii i E.M. Landis n [Ande62], este un arbore binar de cutare echilibrat pe nlime. Un arbore binar de cutare este AVL dac gradul de echilibru al fiecrui nod ia valori n mulimea {-1,0,1}. Pentru a msura gradul de echilibru al unui nod se definete indicatorul GE ce descrie relaia: GE = H(SD) H(SS) (14.1)

unde H() reprezint funcia de calcul a nlimii unei structuri arborescente. Pentru a determina nlimea unui arbore, al crui nod rdcin este rad, se utilizeaz formula: H(rad) = 1 + max (H(subarbore drept), H(subarbore stng)) (14.2)

n care funcia max() este utilizat pentru a determina maximul dintre dou valori.
int max(int valoare_1, valoare_2) { return valoare_1 < valoare_2 ? valoare_2 : valoare_1; }

Pentru valoarea indicatorului GE = 0, nodul este echilibrat, iar pentru valorile 1 si -1, nodul descrie un dezechilibru la dreapta, respectiv la stnga. Figura 14.4, descrie arborele binar de cutare pentru care s-a determinat gradul de echilibru. Situaiile n care GE are valoarea -1 sau 1 sunt acceptate deoarece, pentru un numr par de valori este imposibil sa se defineasc un arbore binar de cutare n care toate nodurile sunt perfect echilibrate.

10 GE = -1 3 GE = 0 2 GE = 0 18

GE = 0 GE = 0 23 GE = 0 27

Figura 14.4 Arbore binar de cutare echilibrat Arborele AVL, reprezint un arbore binar de cutare echilibrat. Pornind de la aceast ipoteza, acest tip de arbore motenete toate operaiile implementate de arborii binari de cutare. Caracteristica de echilibru se gestioneaz prin verificarea atent a gradului de echilibru, pentru fiecare nod n parte, n urma operaiilor de inserare i tergere.

Aceste tipuri de prelucrri afecteaz structura arborelui i conduc la situaii de dezechilibru. Pentru a menine arborele AVL, dup fiecare operaie de inserare, respectiv tergere, sunt cutate situaiile de dezechilibru puternic, identificate prin intermediul nodurilor pentru care indicatorul GE ia valori n mulimea {-2,2}. Reechilibrarea arborelui binar de cutare i pstrarea caracteristicilor aferente arborilor AVL se realizeaz prin operaii de rotire: rotire simpla la stnga; rotire simpla la dreapta; dubla rotire la stnga ; dubla rotire la dreapta. Este important de reinut c printr-o singur rotaie, selectat n funcie de situaie, un arbore AVL dezechilibrat n urma operaiei de inserare va fi reechilibrat. n schimb, operaie de reechilibrare n urma tergerii unui nod este mult mai complex, necesitnd minim o rotaie.

14.3 Operaii pe arbori AVL


Determinarea metodei adecvate de reechilibrare se realizeaz prin analiza gradului de echilibru a nodurilor aflate pe drumul de la rdcina arborelui la locaia n care a fost inserat, respectiv ters, nodul. Se considera situaia din figura 14.4 n care se insereaz nodul cu cheia 1. Arborele binar obinut este:

10 GE = -2 3 GE = -1 2 GE =0 1 GE = 0 18

GE = -1 GE = 0 23 GE = 0 27

Figura 14.5 Arbore binar AVL dezechilibrat n urma procesului de inserarea se recalculeaza gradul de echilibru al nodurilor ce sunt afectate. Aecstea noduri se gasesc in multimea nodurilor {10, 3, 2, 1}. Se observa ca arborele i pierde caracteristica de a fi AVL deoarece nodul cu cheia 3 are un grad de echilibru egal cu -2, ceea ce evideniaz un dezechilibru puternic la stnga. Pentru a aplica procesul de echilibrare, bazat pe operaie de rotire, se identifica un nod, numit pivot, n care se realizeaz rotirea subarborelui.

Selectarea nodului pivot se face printr-o abordare jos-sus pornind de locaia nodului inserat, respectiv, ters ctre rdcina arborelui. Reechilibrarea arborelui se face cat mai aproape de locaia care a generat dezechilibrul. Astfel, printr-un numr minim de rotaii se reconstruiete caracteristica arborelui AVL. n figura, 14.5, nodul pivot este nodul a crui cheie are valoarea 3. Pentru a reechilibra arborele este nevoie s transferm o parte din greutatea subarborelui stng ctre subarborele drept al nodului pivot. Pentru a identifica operaia de rotaie corespunztoare se analizeaz gradul de echilibru al nodului pivot si cel al nodului fiu de pe direcia dezechilibrului. Analiznd arborele din figura 14.4, se observa ca nodul pivot, cu cheia 3, are gradul de echilibru GE = -2, ceea ce implic un dezechilibru la stnga. Deoarece nodul fiu stnga, cu cheia 2, are dezechilibru simplu tot la stnga, reechilibrarea se realizeaz prin operaia de rotire simpl la dreapta, figura 14.6. la
? GE = -2
NOD PIVOT

GE = 0 GE = 0

GE = -1
NOD FIU PE DIRECTIA DEZECHILIBRULUI

X - Subarbore drept pivot

Y - Subarbore stang fiu dreapta pivot

Figura 14.6 Procesul de rotire simpl la dreapta Procesul de rotire simpl la dreapta implic existena a dou elemente principale, nodul pivot, ce este dezechilibrat puternic la stnga i fiul acestuia de pe direcia dezechilibrului, care este la rndul su dezechilibrat slab tot la stnga. Pentru a reechilibra arborele n aceast situaie este necesar i suficient s scdem cu o unitate nlimea subarborelui stng al pivotului i s cretem cu o unitate nlimea subarborelui drept. Pentru a atinge acest obiectiv, se modific cele dou legturi evideniate n figura 14.5. Se observ c subarborele Y devine subarbore drept pentru nodul pivot, fapt ce nu contrazice existena unui arbore binar de cutare deoarece toate valorile din acest subarbore sunt mai mici dect valoarea nodului pivot. Prin aplicarea procesului de rotire, arborele se reechilibreaz i i pstreaz caracteristicile specifice unui arbore AVL i unui arbore binar de cutare. Se observ c prin rotaia simpl la dreapta sunt afectate doar gradele de echilibru ale nodului pivot i nodului fiu de pe direcia dezechilibrului, nodul fiu stnga. Prin modificarea structurii arborescente, cele dou noduri devin perfect echilibrate, GE = 0. Explicaia este dat de faptul c nodul fiu stnga urc pe nivelul superior n locul nodului printe, iar acesta, fiind nod pivot, coboar n subarborele drept. Figura 14.7

utilizeaz ca reper nlimea subarborelui Y pentru a descrie modul n care se ajunge la acest rezultat. Este evideniat modul de calcul al indicatorului GE pentru a sublinia modul n care se ajunge la rezultat.
?
NOD PIVOT

GE = H1 (H1 + 2) = -2

GE = 0 GE = 0

2 GE = H1 (H1 + 1) = -1 H1+2 H1+1 Z Y

H1

H1+1

3 H1+1

H1

H1

X H1

Figura 14.7 Procesul de rotire simpl la dreapta Metoda clasei AVLArbore ce implementeaz aceast rotaie simpl primete ca parametru referina la nodul pivot.
void AVLArbore::RotatieSimplaDreapta(AVLNod * &pivot) { AVLNod *FiuStanga = pivot->st; pivot->st = FiuStanga->dr; FiuStanga->dr = pivot; pivot->Echilibru = 0; FiuStanga->Echilibru = 0; pivot = FiuStanga; }

Aplicnd aceast metod arborescent din figura 14.8.

arborelui

analizat,

rezult

structura

10 GE = 0 2 GE = 0 1 GE =0 GE = 0 3 18

GE = 0 GE = 0 23 GE = 0 27

Figura 14.8 Arbore AVL reechilibrat Dac prin inserarea sau tergerea unui nod se ajunge n situaia din figura 14.9, reechilibrarea arborelui se realizeaz printr-o rotire simpl la stnga.

10 GE = -1 2 GE =0 1

GE = 1 GE = 2 23 GE = 1 27 GE = 0 30

Figura 14.9 Arbore AVL dezechilibrat n aceast situaie, pivotul este dat de nodul cu valoarea 23, acesta fiind puternic dezechilibrat la dreapta, GE = 2. Deoarece nodul fiu dreapta, este dezechilibrat slab pe aceeai direcie, reechilibrarea se realizeaz prin operaia de rotire simpl la stnga.
?
NOD PIVOT

? GE = 2 23 GE = 1
NOD FIU PE DIRECTIA DEZECHILIBRULUI

GE = 0 GE = 0 23

30

X - Subarbore stng pivot

30

Y - Subarbore stang fiu stnga pivot

Figura 14.10 Procesul de rotire simpl la stnga Asemntor operaiei de rotaie simpl la dreapt, cele dou noduri afectate direct de reorganizarea legturilor, nodul pivot i fiul acestuia din dreapta, au n final grade de echilibru egale cu valoarea zero. Reorganizarea celor dou legturi evideniate n figura 14.10 are ca efect reducerea cu o unitate a nlimii subarborelui drept al nodului pivot i creterea cu o unitate a subarborelui stng. Metoda ce implementeaz aceast operaie, RotatieSimplaStanga, are ca parametru de intrare referina nodului pivot.
void AVLArbore::RotatieSimplaStanga(AVLNod * &pivot) { AVLNod *FiuDreapta = pivot->dr; pivot->dr = FiuDreapta->st; FiuDreapta->st = pivot;

pivot->Echilibru = 0; FiuDreapta->Echilibru = 0; pivot = FiuDreapta; }

Aplicnd aceast operaie arborelui din figura 14.10 se obine arborele AVL:

10 GE = -1 2 GE =0 1 GE = 0 23

GE = 1 GE = 0 27 GE = 0 30

Figura 14.11 Arbore AVL reechilibrat n cazul operaiile de rotire duble, situaia iniial este caracterizat de sensuri opuse de dezechilibru pentru nodul pivot si pentru nodul su fiu de pe direcia dezechilibrului. Pentru a exemplifica o astfel de situaie se insereaz n arborele AVL din figura 14.11, elementele cu valorile 16, 24, 26. Structura arborescent obinut este:

10 GE = -1 2 GE =0 1 GE = 0 16 GE = 1 23

GE = 2

27

GE = -2 GE = 0 30

GE = 1 24 GE = 0 26

Figura 14.12 Arbore AVL dezechilibrat Structura arborescent din figura 14.12 nu este arbore AVL deoarece exist noduri pentru care gradul de echilibru, GE, are valori n mulimea {-2, +2}. Situaia este generat de inserarea nodului cu valoarea 26, iar analiza drumului de la acest nod napoi ctre nodul rdcin conduce la

identificarea pivotului, nodul cu valoarea 27. Se observ c, acest nod este puternic dezechilibrat la stnga, iar nodul fiu de pe aceast direcie, nodul 23, este dezechilibrat slab pe direcia opus. Soluia pentru aceast problem necesit o abordare diferit de cele dou tipuri de rotiri simple descrise, deoarece acestea nu conduc la reechilibrarea arborelui. Pentru a exemplifica aceast abordare greit se simuleaz o rotire simpl la dreapta aplicat pivotului. Rezultatul obinut este:
10 GE = -1 2 GE =0 1 GE = 0 16 GE = 1 24 30 GE = 0 GE = 0 26 23 GE = -1 27 GE = 2 GE = 2

Figura 14.13 Arbore AVL dezechilibrat Se observ c arborele, figura 14.13, este n continuare dezechilibrat, numai c de data aceasta, dezechilibrul este n sens opus. ncercarea reechilibrrii, tot cu o rotire simpl, dar n sens opus, va conduce la obinerea ipotezei iniiale, descris n figura 14.12. Soluia eficient a acestui tip de dezechilibru este dat de aplicarea unei rotiri duble, ce const n aplicarea a dou rotiri simple. Scopul primei rotiri este de a rearanja structura arborescent astfel nct direciile dezechilibrului nodului pivot i a fiului acestuia s aib acelai sens. Cea dea doua rotire are ca obiectiv reechilibrarea arborelui. Pe baza acestor motive, cele dou rotaii sunt aplicate unor noduri diferite. Prima rotaie se aplic nodului fiu al nodului pivot, nod ce se gsete pe direcia dezechilibrului. Sensul acestei prime rotiri este identic cu direcia dezechilibrului. A dou rotire simpl se aplic nodului pivot i are sens opus dezechilibrului. Pentru structura arborescent din figura 14.12, pivotul este dat de nodul cu valoarea 27 i acesta este puternic dezechilibrat la stnga. Pentru a reechilibra arborele se parcurg urmtoarele etape: - se analizeaz nodul fiu al nodului pivot pe direcia dezechilibrului; acest nod are valoarea 23 i este slab dezechilibrat la dreapta; - deoarece pivotul i nodul fiu sunt dezechilibrate pe direcii diferite, reechilibrarea se realizeaz printr-o dubl rotaie; - prima rotaie se aplic nodului fiu i are sens identic cu dezechilibrul nodului pivot; se observ c aceast operaie intermediar, figura 14.12.a, redefinete situaia aducnd-o ntr-o form specific cazurilor n care se aplic rotaii simple;

a doua rotaie se dezechilibrului.


10 GE = -1 2 27 GE = 1
NOD FIU

aplic nodului pivot i are sens opus

GE = 2 GE = -2
NOD PIVOT

10 GE = -1 2 GE =0 30 1 GE = -1 23 GE = 0 GE = 0 GE = -1 24

GE = 2 GE = -2 27
NOD PIVOT

GE =0 1

GE = 0 30 GE = 0 26

23 GE = 1 24

GE = 0 16

GE = 0

A) ROTATIE SIMPLA LA STANGA

26

16

B) ROTATIE SIMPLA LA DREAPTA

10 GE = -1 2 GE =0 1 GE = 0 16 GE = -1 23

GE = 1 GE = 0 24 GE = 0 27 GE = 0 26 GE = 0 30

C) ARBORE REECHILIBRAT

Figura 14.14 Rotaia dubl la dreapta Din analiza dublei rotaii la dreapta sunt evideniate 3 elemente importante, n funcie de care sunt reiniializate o serie de legturi: - nodul pivot, puternic dezechilibrat la stnga, GE = -2; - fiul stnga la pivotului, FiuStanga ,ce este slab dezechilibrat la dreapta, GE = 1; - fiul dreapta al nodului FiuStanga, notat cu FiuStanga_FiuDreapta; n funcie de situaie, acest nod prezint un grad de echilibru ce ia valori n mulimea {-1, 0 , 1}. Pentru a determina gradul de echilibru final al nodurilor afectate de dubla rotaie, se analizeaz modul n care se distribuie nlimea subarborilor n urma rotaiilor. Tabelul 14.1 descrie situaiile iniiale i rezultatele la care se ajunge n urma reechilibrrii. Tabelul nr. 14.1 Rezultatul operaiei de dubl rotaie la dreapta Situaie iniial
Pivot FiuStanga FiuStanga_FiuDreapta Pivot

Situaie final
FiuStanga FiuStanga_FiuDreapta

-2 -2 -2

+1 +1 +1

-1 0 +1

1 0 0

0 0 -1

0 0 0

Situaia descris n tabelul anterior este utilizat pentru a defini mai eficient metoda care implementeaz acest tip de rotaie. Astfel este evitat efortul suplimentar de a recalcula gradul de echilibru pentru cele trei noduri afectate.

Clasa AVLArbore implementeaz aceast operaie prin intermediul metodei RotatieDublaDreapta ce primete ca parametrul referina nodului pivot.
void AVLArbore::RotatieDublaDreapta(AVLNod * &pivot) { AVLNod *FiuStanga, *FiuStanga_FiuDreapta; FiuStanga = pivot->st; FiuStanga_FiuDreapta = FiuStanga->dr; //realizare rotatie 1 - simpla stanga FiuStanga->dr = FiuStanga_FiuDreapta->st; FiuStanga_FiuDreapta->st = FiuStanga; //realizare rotatie 2 - simpla dreapta pivot->st = FiuStanga_FiuDreapta->dr; FiuStanga_FiuDreapta->dr = pivot; //modificare grade de echilibru if(FiuStanga_FiuDreapta->Echilibru == 1) { pivot->Echilibru = 0; FiuStanga->Echilibru = -1; } else if(FiuStanga_FiuDreapta->Echilibru == 0) { pivot->Echilibru = 0; FiuStanga->Echilibru = 0; } else { pivot->Echilibru = 1; FiuStanga->Echilibru = 0; } FiuStanga_FiuDreapta->Echilibru=0; pivot = FiuStanga_FiuDreapta; }

Structura arborescent este modificat prin tergerea nodului cu valoarea 16 i prin adugarea unei noi valori, 25. Arborele obinut, descris n figura 14.15, nceteaz s mai fie AVL n urma aplicrii ultimei modificri.
10 GE = -1 2 GE =0 1 GE = -1 23 GE = -1 26 GE = 0 25 24 GE = -1 27 GE = 0 30 GE = 2 GE = 2

Figura 14.15 Arbore AVL dezechilibrat

Se observ c exist dou noduri, cu valoarea 24 i 10, ce descriu dezechilibre puternice, GE = 2, la dreapta. Analiznd, de jos n sus, drumul de la noul nod inserat la rdcin arborelui, se stabilete ca fiind pivot nodul cu valoarea 24. n mod asemntor cu situaia descris anterior, fiul pivotului de pe direcia dezechilibrului este dezechilibrat uor n sens opus. Tentativa de a rezolva situaia prin intermediul unei rotaii simple nu conduce la soluionarea problemei reechilibrrii deoarece are ca rezultat mutarea dezechilibrului pe partea stng. Avnd n vedere condiiile de lucru, reechilibrarea arborelui din figura 14.15 presupune: - aplicarea unei rotaii simple la dreapta n nodul fiu al pivotului; dac pivotul are ambii fii atunci rotaia se face n toate situaiile asupra nodului fiu de pe direcia dezechilibrului; deoarece pivotul este dezechilibrat puternic la dreapta, nodul fiu selecta este 27; - aplicarea unei rotaii simple la stnga, n sens opus dezechilibrului, n nodul pivot.
10 GE = -1 2 GE =0 1 GE = -1 23 GE = -1 26 GE = 0 25
A) ROTATIE SIMPLA LA DREAPTA B) ROTATIE SIMPLA LA STANGA

GE = 2 GE = 2 24 GE = -1 27
NOD FIU

10 GE = -1 2 GE =0 1 GE = -1 23

GE = 2 GE = 2 24 GE = 1 26 GE = 0 25
NOD FIU

NOD PIVOT

NOD PIVOT

GE = 0 30

GE = 1 27

GE = 0

30

10 GE = -1 2 GE =0 1 23 GE = 0 24

GE = 1 GE = 0 26 GE = 1 27 GE = 0 GE = 0 30

GE = 0

25
C) ARBORE REECHILIBRAT

Figura 14.16 Rotaia dubl la stnga Pentru a implementa o soluie software care s gestioneze datele prin intermediul unui arbore binar de cutare echilibrat de tip AVL, trebuie s fie dezvoltate rutine complementare operaiilor de inserare i tergere n arbori binari de cutare care s reechilibreze structura arborescent aflat n una din cele patru situaii descrise. Tabelul 14.2 sintetizeaz situaiile de dezechilibru i modul n care arborele AVL este meninut n urma operaiilor de inserare.

Tabelul nr. 14.2 Situaii dezechilibru arbori AVL


Grad echilibru nod pivot Nod fiu analizat Grad echilibru nod fiu Rotire

+2 +2 -2 -2

dreapta dreapta stnga stnga

+1 -1 -1 +1

Simpl la stnga Dubl la stnga: rotire simpl la dreapta n fiul din dreapta al pivotului; rotire simpl la stnga n pivot. Simpl la dreapta Dubl la dreapta: rotire simpl la stnga n fiul din stnga al pivotului; rotire simpl la dreapta n pivot.

Dezvoltarea de aplicaii care implementeaz lucrul cu arbori de tip AVL se bazeaz pe dezvoltarea unei biblioteci de cod n care sunt definite clasele AVLNod i AVLArbore. Clasa AVLNod descrie atributele i metodele unui obiect ce reprezint nodul unui arbore binar de cutare echilibrat.
class AVLNod { private: int Echilibru; int Info; AVLNod *st; AVLNod *dr; public: //constructorii clasei AVLNod(void); AVLNod(int echilibru, int info, AVLNod * stanga, AVLNod * dreapta); //destructorul clasei virtual ~AVLNod(void); //interfata pentru atributul Echilibru int GetEchilibru(void){return this->Echilibru;}; // acces la atributele private din clasa AVLArbore friend class AVLArbore; //acces la atributele private din clasa AVLNodeStack friend class AVLNodeStack; };

n comparaie cu nodul unui arbore binar de cutare, aceast clas definete o proprietate nou, Echilibru, utilizat pentru a gestiona gradul de echilibru asociat fiecrui nod. Atributele Info, st i dr sunt utilizate pentru a memora valoarea nodului curent i pentru a face legtur ntre nodul printe i nodul fiu stnga, respectiv, dreapta. Cele dou metode constructor
AVLNod::AVLNod(void) { Echilibru = 0; Info = 0; st = NULL; dr = NULL;

} AVLNod::AVLNod(int echilibru, int info, AVLNod * stanga, AVLNod * dreapta) { Echilibru = echilibru; Info = info; st = stanga; dr = dreapta; }

permit programatorilor crearea i iniializarea unui nod al arborelui cu valori implicite sau pe baza unor parametrii de intrare. Clasa AVLArbore definete atributele i metodele unui obiect de tip arbore AVL. Acesta gestioneaz structura dinamic de elemente prin intermediul referinei ctre nodul rdcin, radacina.
class AVLArbore { public: AVLNod *radacina; public: //constructorul clasei AVLArbore(void); //constructorul de copiere al clasei AVLArbore(const AVLArbore & arbore); //destructorul clasei virtual ~AVLArbore(void); //operatorul = AVLArbore operator = (AVLArbore & arbore); //metodele clasei pentru inserare/stergere nod void Insert(const int info); void Delete(const int info); //metoda pentru afisarea arborelui static void AfisareArbore(AVLNod * rad); //metoda pentru stergerea arborelui void StergereArbore(AVLNod * &rad); private: void AVLInsert(AVLNod* &arbore,AVLNod * nodNou, int & echilibruNou); void AVLDelete(AVLNod* &arbore,const int Info,AVLNodeStack &stiva); //rotatii simple utilizate la inserare void RotatieSimplaDreapta(AVLNod * &pivot); void RotatieSimplaStanga(AVLNod * &pivot); //rotatii simple utilizate la stergere void RotatieSimplaDreaptaStergere(AVLNod * &pivot); void RotatieSimplaStangaStergere(AVLNod * &pivot); void RotatieDublaDreapta(AVLNod * &pivot); void RotatieDublaStanga(AVLNod * &pivot); //metodele clasei pentru reechilibrarea arborelui

void ReechilibrareSubarboreStang(AVLNod * &pivot, int &echilibruNou); void ReechilibrareSubarboreDrept(AVLNod * &pivot, int &echilibruNou); //metoda utilizata pentru copierea arborelui void CopiereArbore(AVLArbore &arboreNou, AVLNod * rad); //metoda inserare a unui arbore binar de cautare AVLNod * Inserare(AVLNod *rad, const int Valoare, int echilibru = 0); static int Stergere(AVLNod*& Subarbore, AVLNodeStack &stiva); //metoda pentru determinarea inaltimii unui arbore int inaltime(AVLNod * radacina); //metoda ce determina maximul dintre doua valori int max(int a, int b){return a < b? b : a;} //metoda ce determina gradul de echilibru al nodului int CalculeazaEchilibru(AVLNod *& radacina); //metoda recalculeaza gradul de echilibru pentru toate nodurile void RecalculeazaEchilibrul(AVLNod *&rad); };

O atenie deosebit se acord formei dat de programator a constructorului de copiere i a operatorului =. Necesitatea este dat de existena atributului dinamic AVLNod *radacina i de efectele negative pe care le au formele implicite ale acestor dou metode asupra programului. Programatorul trebuie s se asigure c n situaiile n care aceste dou metode sunt apelate se vor crea structuri noi cu valori egale i nu se vor face doar simple iniializri de referine ctre aceeai zon de memorie. Copierea arborelui presupune parcurgerea structurii existente, cu pstrarea caracteristicilor acesteia. Din acest motiv, cele dou metode se bazeaz pe o parcurgere n preordine a arborelui existent, completat de inserarea nodului curent n structura nou creat. Spre deosebire de parcurgere n inordine i postordine, parcurgere n preordine asigur crearea unui nou arbore binar de cutare identic cu structura surs i cu minim de efort. Se consider structura arborescent din figura 14.17 pentru care se obin irurile valorilor elementelor, parcurgnd arborele prin cele trei metode cunoscute.
10 Preordine: 10, 3, 2, 23, 18, 27 Inordine: 2, 3, 10, 18, 23, 27 Postordine: 2, 3, 18, 27, 23, 10

23

18

27

Figura 14.17 Structur arborescenta de tip AVL

Prin inserarea valorilor ntr-o nou structur arborescent, pe msur ce acestea sunt accesate i analizate, se obin cei trei arbori binari de cutare din figura 14.18.
10 2 3 3 23 10 2 18 27 18 23 A) Arbore obinut n urma parcurgerii n preordine B) Arbore obinut n urma parcurgerii n inordine 27 3 23 C) Arbore obinut n urma parcurgerii n postordine 18 27 2 3

Figura 14.18 Structuri arborescente binare Se observ c, dintre cele trei metode de parcurgere a unui arbore binar, cea mai potrivit pentru operaia de copiere este abordarea n preordine. Celelalte dou metode necesit un efort suplimentar de rearanjare a nodurilor i nu asigur obinerea unei arbore identic cu sursa. Din punct de vedere al reechilibrrii, efortul este mult mai mare datorit prelucrrilor suplimentare. Metoda CopiereArbore construiete copia arborelui radArboreVechi parcurgnd-ul n preordine.
void AVLArbore::CopiereArbore(AVLArbore &arboreNou, AVLNod *radArboreVechi) { if(radArboreVechi!=NULL) { arboreNou.radacina = arboreNou.Inserare(arboreNou.radacina,radArboreVechi->Info, radArboreVechi->Echilibru); CopiereArbore( arboreNou, radArboreVechi->st); CopiereArbore( arboreNou, radArboreVechi->dr); } }

Metoda anterior, se bazeaz pe parcurgerea recursiv a arborelui curent i apeleaz rutina Inserare specific arborilor binari de vutare pentru a insera o valoare ntr-o nou structur arborescent gestionat prin pointerul arboreNou.
AVLNod * AVLArbore::Inserare(AVLNod *rad, const int Valoare, int echilibru) { if(rad == NULL) { rad = new AVLNod(echilibru,Valoare, NULL, NULL); } else if(rad->Info<Valoare) rad->dr = Inserare(rad->dr,Valoare,echilibru);

else if(rad->Info>Valoare) rad->st = Inserare(rad->st,Valoare,echilibru); return rad; }

Formele explicite ale constructorului de copiere i a operatorului de egal implementeaz rutina de copiere a unui arbore pentru a genera noi structuri arborescente cu valori identice.
AVLArbore::AVLArbore(const AVLArbore &arbore) { this->radacina = NULL; CopiereArbore((*this),arbore.radacina); }

Spre deosebire de constructorul de copiere, operatorul = presupune tergerea arborelui existent i recrearea acestuia prin copierea valorilor structurii arbore.
AVLArbore AVLArbore::operator = (AVLArbore & arbore) { StergereArbore(this->radacina); CopiereArbore((*this),arbore.radacina); return *this; }

Metoda utilizat pentru tergerea arborelui AVL este dat de operaia specific structurilor arborescente binare, ce realizeaz eliberarea memoriei de jos n sus, pornind cu nodurile frunz.
void AVLArbore::StergereArbore(AVLNod * &rad){ if(rad!=NULL){ StergereArbore(rad->st); StergereArbore(rad->dr); delete rad; rad = NULL; } }

Operaia de inserare n arborii AVL este derivat din metoda specific arborilor binari de cutare. Operaiile suplimentare sunt necesare procesului de reechilibrare i de conservare a caracteristicii acestui tip de structur, meninerea gradului de echilibru n mulimea {-1; 0; 1} pentru toate nodurile arborelui. Metoda AVLInsert parcurge o serie de etape necesare inserrii unui nou nod, nodNou, ntr-un arbore de tip AVL, gestionat prin intermediul pointerului arbore: - dac arborele este vid, noul nod devine rdcina arborelui AVL; - dac arborele exist, se caut poziia noului nod prin parcurgerea acestuia asemenea unui arbore binar de cutare; parcurgerea este recursiv, accesndu-se nodul fiu stnga sau dreapta funcie de rezultatul comparrii valorii nodului nou cu valoarea nodului curent;

se recalculeaz gradul de echilibru pentru toate nodurile parcurse; fiind un proces recursiv, revenirea din apelul rutinei asigur poziionarea pe nodul anterior; variabilele echilibruNou i Reechilibrare indic faptul c a avut loc o modificare de structur n apelul anterior, lucru care poate conduce la dezechilibre; n cazul n care aceste variabile sunt iniializate cu valoare 1, este testat gradul de echilibru al nodului curent;

void AVLArbore::AVLInsert(AVLNod* &arbore,AVLNod * nodNou, int & echilibruNou){ int Reechilibrare; if(arbore == NULL){ arbore = nodNou; arbore->Echilibru = 0; echilibruNou = 1; } else if(nodNou->Info<arbore->Info){ AVLInsert(arbore->st,nodNou,Reechilibrare); if(Reechilibrare){ if(arbore->Echilibru == -1) ReechilibrareSubarboreStang(arbore,echilibruNou); else if(arbore->Echilibru == 0){ arbore->Echilibru = -1; echilibruNou = 1; } else{ arbore->Echilibru = 0; echilibruNou = 0; } } else echilibruNou = 0; } else{ if(nodNou->Info>arbore->Info){ AVLInsert(arbore->dr, nodNou, if(Reechilibrare){ if(arbore->Echilibru == arbore->Echilibru = 0; echilibruNou = 0; } else if(arbore->Echilibru == arbore->Echilibru echilibruNou = 1; } else Reechilibrare); -1){

0){ = 1;

ReechilibrareSubarboreDrept(arbore,echilibruNou); } else echilibruNou = 0; } else echilibruNou = 0;

}}

identificarea nodului dezechilibrat, pivotul operaiilor de rotire, este realizat doar dac variabila Reechilibrare este setat, prin verificarea elementelor vizitate; dac nodul curent are gradul de echilibru egal cu -1 iar nodul nou a fost inserat n subarborele stng, are loc reechilibrarea acestuia prin apelul metodei ReechilibrareSubarboreStang; dac nodul curent are gradul de echilibru egal cu 0 sau +1 iar nodul nou a fost inserat n subarborele stng, atunci noul grad de echilibru al elementului curent este -1, respectiv 0; prin iniializarea variabilei echilibruNou cu valoare 1 se continu verificarea dezechilibrului la nodurile superioare; dac nodul curent devine perfect echilibrat, se oprete verificarea n acest punct, iar echilibruNou ia valoarea 0; dac nodul curent are gradul de echilibru egal cu +1 iar nodul nou a fost inserat n subarborele drept, are loc reechilibrarea acestuia prin apelul metodei ReechilibrareSubarboreDrept; dac nodul curent are gradul de echilibru egal cu 0 sau -1 iar nodul nou a fost inserat n subarborele drept, atunci noul grad de echilibru al elementului curent este +1, respectiv 0; asemenea situaiei anterioare, variabila echilibruNou condiioneaz prin valorile ei continuarea sau ncetarea procesului de cutare; metoda ReechilibrareSubarboreStang ia n considerare toate situaiile posibile de dezechilibru ctre stnga i n funcie de tipul acesteia reechilibreaz subarborele cu rdcina n nodul pivot prin rotaie simpl la dreapta, metoda RotatieSimplaDreapta, sau prin rotaie dubl la dreapta, metoda RotatieDublaDreapta; se observ caracterul general al acestei metode de reechilibrare ce este utilizat i la tergerea unui nod, procesul fiind descris n continuare;

void AVLArbore::ReechilibrareSubarboreStang(AVLNod * &pivot, int &echilibruNou){ AVLNod * FiuStanga = pivot->st; if(FiuStanga->Echilibru == -1){ RotatieSimplaDreapta(pivot); echilibruNou = 0; } else if(FiuStanga->Echilibru == 1){ RotatieDublaDreapta(pivot); echilibruNou = 0; } else //situatie specifica operatiei de stergere if(FiuStanga->Echilibru == 0){ RotatieSimplaDreaptaStergere(pivot); echilibruNou = 0; } }

metoda ReechilibrareSubarboreDrept analizeaz cazurile de dezechilibru la dreapta, reechilibrnd pivotul prin una din cele dou tehnici de rotaie la stnga;

void AVLArbore::ReechilibrareSubarboreDrept(AVLNod * &pivot, int &echilibruNou){ AVLNod * FiuDreapta = pivot->dr; if(FiuDreapta->Echilibru == 1){ RotatieSimplaStanga(pivot); echilibruNou = 0; } else if(FiuDreapta->Echilibru == -1){ RotatieDublaStanga(pivot); echilibruNou = 0; } else //situatie specifica operatiei de stergere if(FiuDreapta->Echilibru == 0){ RotatieSimplaStangaStergere(pivot); echilibruNou = 0; } }

Metoda AVLInsert este o metod intern clasei. Aceasta este epelat din programul principal de ctre metoda public Insert ce primete ca parametru valoarea de inserat n arborele AVL.
void AVLArbore::Insert(const int info) { AVLNod* RadacinaArbore = this->radacina; AVLNod* NodNou = new AVLNod(0,info,NULL,NULL); int EchilibruNou = 0; AVLInsert(RadacinaArbore,NodNou,EchilibruNou); this->radacina = RadacinaArbore; }

Spre deosebire de operaie de inserare, care necesit maxim o singur rotaie pentru remedierea dezechilibrului, n cazul procedurii de tergere a unui nod sunt necesare mai multe operaii de rotaie pentru a reechilibra arborele AVL i pentru a conserva caracteristicile acestuia. Etapele parcurse se concentreaz pe analiza tuturor nodurilor direct influenate - se identific nodul de ters pe baza caracteristicilor arborilor binari de cutare; - pe msur ce se parcurge arborele, nodurile vizitate sunt salvate ntr-o structur de tip stiv; aceast operaie suplimentar este necesar pentru a permite reconstruirea n sens invers a drumului parcurs de la rdcina arborelui;

struct NodeStack { AVLNod* Nod; NodeStack *next; }; class AVLNodeStack { private: NodeStack * VarfStiva; public: AVLNodeStack() { VarfStiva=NULL; } void PUSH(AVLNod* &NodNou){ NodeStack *elementNou= new NodeStack; elementNou->Nod = NodNou; if(this->VarfStiva==NULL){ this->VarfStiva = elementNou; elementNou->next=NULL; } else { elementNou->next = this->VarfStiva; this->VarfStiva = elementNou; } } AVLNod* POP(){ if(this->VarfStiva==NULL) return NULL; else { NodeStack *elementSters = this->VarfStiva; AVLNod* NodAuxiliar = this->VarfStiva->Nod; this->VarfStiva = this->VarfStiva->next; delete elementSters; return NodAuxiliar; } } void AfiseazaStiva() { NodeStack *temp = this->VarfStiva; while(temp!=NULL) { printf("\n Nod in stiva este %d",temp->Nod->Info); temp=temp->next; } } };

nodul se terge n mod asemntor cu operaia asociat arborilor binari de cutare; dac nodul este frunz se terge efectiv; dac nodul are un singur fiu, acesta l nlocuiete n structur; dac nodul are cei doi fii, este nlocuit de nodul cu valoarea cea mai mare din subarborele drept, metoda Stergere;

int AVLArbore::Stergere(AVLNod*& SubarboreDrept, AVLNodeStack &stiva ) { if(SubarboreDrept->st) { stiva.PUSH(SubarboreDrept); return AVLArbore::Stergere(SubarboreDrept->st,stiva); } else { AVLNod * NodSters= SubarboreDrept; int valoare = SubarboreDrept->Info; SubarboreDrept = SubarboreDrept->dr; delete NodSters; return valoare; } }

sunt analizate toate nodurile parcurse i sunt reechilibrate situaiile de dezechilibru lund n calcul ipotezele de aplicare a celor patru tipuri de rotaii; operaia de tergere se ncheie n momentul n care sunt verificate toate locaiile de dezechilibru posibil; pentru abordarea aleas ca soluie n acest capitol, operaia se consider ncheiat n momentul n care stiva este golit; din analiza metodei Stergere, se observ c n etapa de identificare a nodului cu valoarea ce mai mare din subarborele drept, ce va lua locul nodului de ters, este completat de salvarea n stiva utilizat a nodurilor vizitate; necesitatea acestei operaii suplimentare este dat de faptul c tergerea unui nod poate conduce la dezechilibrarea nodurilor superioare aflate pe drumul de la rdcin la poziia lui; de asemenea, reechilibrarea unui nod printe poate conduce la generarea unei alte situaii de dezechilibru; pentru a exemplifica aceast situaie, se ia n considerare arborele AVL din figura 14.19 n care se terge nodul cu valoarea 50;
47 35

35
stiva
GE = -1

22
GE = 1

47 31
GE = -1

GE = -1

16
GE = -1

37
GE = 1

50
GE =0

9
GE =0

27
GE = -1

32
GE =0

42
GE =0

29
GE =0

Figura 14.19 Structur arborescenta de tip AVL Prin tergerea nodului cu valoarea 50, se obine stiva cu valorile 47 i 35. Din analiza acestor noduri, se observ c arborele AVL, descris n figura 14.20, devine dezechilibrat n nodul cu valoarea 47.

35
35 stiva
GE = -1

35
GE = -2

22
GE = 1

47 31
GE = -1

GE = -2

22
GE = 1

37 31
GE = -1

GE =0

16
GE = -1

37
GE = 1 GE = -1

16 9
GE =0

42
GE = 0 GE =0

47
GE =0

9
GE =0

27
GE = -1

32
GE =0

42
GE =0

27
GE = -1

32 29
GE =0

29
GE =0

Figura 14.20 Structur arborescenta de tip AVL dezechilibrat Prin reechilibrare, aplicnd o rotaie simpl la dreapta n pivot, se obine o nou situaie de dezechilibru n urmtoare valoare din stiv, 35, figura 14.20. Printr-o rotaie simpl la dreapta n nodul cu valoarea 35 considerat pivot, arborele AVL este reechilibrat. Deoarece stiva a fost golit, operaie de tergere se consider ncheiat, figura 14.21.
35
GE = -2 GE =0 GE =0

31 35 GE = -1
GE =0

22

22
GE = 1

(2)

37

GE =0

16 16
GE = -1

27
GE = 1

32

(1)

31
GE = -1

37 GE =0

42
GE = 0 GE =0

47
GE =0

GE = -1

9
GE =0

27
GE = -1

32 29
GE =0

9
GE =0 GE =0

29
GE =0

42
GE = 0

47

Figura 14.21 Structur arborescenta de tip AVL Exist cazuri n care prin tergerea unui nod, se ajunge la situaii de dezechilibru diferite de ipotezele analizate la operaia de inserare. Lund n considerare arborele AVL din figura 14.22, se propune tergerea nodului cu valoarea 16.
17
GE = 1

17

GE = 2

20
GE = -1

16
GE =0

20
GE = 0

20
GE = 0

17
GE = -1

23
GE = 0

19
GE =0

23
GE =0

19
GE =0

23
GE =0

19
GE =0

Figura 14.22 tergere din structur arborescenta de tip AVL Situaia difer de cele ntlnite la inserare prin faptul c n acest dezechilibru pivotul are un grad de echilibru egal cu +2, iar nodul fiu de pe direcia dezechilibrului are un echilibru egal cu 0. Soluia acestui dezechilibru este dat de o rotaie simpl n pivot la stnga.

Din acest motiv, metodele clasei AVLArbore, destinate analizei i implementrii tipului de rotaie potrivit, sunt modificate n cazul operaiei de tergere. Cele dou metode descrise anterior , ReechilibrareSubarboreDrept i ReechilibrareSubarboreStang analizeaz i situaiile particulare n care nodul de pe direcia dezechilibrului are gradul de echilibru egal cu zero, caz n care sunt apelate metodele RotatieSimplaDreaptaStergere i RotatieSimplaStangaStergere.
void AVLArbore::RotatieSimplaDreaptaStergere(AVLNod * &pivot) { AVLNod *FiuStanga = pivot->st; pivot->st = FiuStanga->dr; FiuStanga->dr = pivot; pivot->Echilibru += 1; FiuStanga->Echilibru += 1; pivot = FiuStanga; } void AVLArbore::RotatieSimplaStangaStergere(AVLNod * &pivot) { AVLNod *FiuDreapta = pivot->dr; pivot->dr = FiuDreapta->st; FiuDreapta->st = pivot; pivot->Echilibru -=1; FiuDreapta->Echilibru -= 1; pivot = FiuDreapta; }

Pentru a implementa operaia de tergere, se definete n clasa AVLArbore metoda Delete.


void AVLArbore::Delete(const int Info) { int valTemp; //definesc stiva nodurilor parcurse AVLNodeStack stiva; //se sterge nodul AVLDelete(this->radacina,Info,stiva); //se analizeaza nodurile parcurse AVLNod *temp = stiva.POP(); while(temp!=NULL){ temp->Echilibru = this->CalculeazaEchilibru(temp); if(temp->Echilibru==2){ AVLNod *parinte = stiva.POP(); if(parinte!=NULL){ if(parinte->dr==temp) this->ReechilibrareSubarboreDrept(parinte->dr,valTemp); else this->ReechilibrareSubarboreDrept(parinte->st,valTemp); parinte->Echilibru=this->CalculeazaEchilibru(parinte); } }

else if(temp->Echilibru==-2){ AVLNod *parinte = stiva.POP(); if(parinte!=NULL){ if(parinte->dr==temp) this->ReechilibrareSubarboreStang(parinte->dr,valTemp); else this->ReechilibrareSubarboreStang(parinte->st,valTemp); parinte->Echilibru=this->CalculeazaEchilibru(parinte); } } temp=stiva.POP(); } }

Aceast metod se bazeaz pe apelul metodei AVLDelete pentru a realiza tergerea efectiv a nodului dorit, secvena de cod asociat fiind concentrat pe analiza nodurilor din stiva. Pentru fiecare din acestea, se recalculeaz gradul de echilibru prin intermediul metodei CalculeazaEchilibru.
int AVLArbore::CalculeazaEchilibru(AVLNod *& radacina) { return inaltime(radacina->dr) - inaltime(radacina->st); }

Metoda AVLDelete completeaz metoda ntlnit la tergerea nodurilor din arbori binari de cutare prin gestiunea unei stive n care sunt inserate toate valorile ntlnite.
void AVLArbore::AVLDelete(AVLNod* &arbore,const int Info,AVLNodeStack &stiva){ AVLNod *NodAuxiliar; if(arbore){ if(Info == arbore->Info){ NodAuxiliar = arbore; if(!NodAuxiliar->dr){ arbore = NodAuxiliar->st; delete NodAuxiliar; } else if(!NodAuxiliar->st){ arbore = NodAuxiliar->dr; delete NodAuxiliar; } else{ stiva.PUSH(arbore); arbore->Info = AVLArbore::Stergere(arbore->dr,stiva); } } else if(Info < arbore->Info){ stiva.PUSH(arbore); AVLDelete(arbore->st,Info,stiva); } else{ stiva.PUSH(arbore); AVLDelete(arbore->dr,Info,stiva); }

} }

n ciuda efortului asociat implementrii i executrii secvenelor de rotire ale structurii, arborii AVL ofer un ridicat nivel de eficien n ceea ce privete procesul de cutare n arbori binari de cutare. Structura arborescent echilibrat

14.4 Caracteristici ale arborilor Rou & Negru


Arborii Rou & Negru reprezint o alt tipologie de arbori binari de cutare echilibrai, fiind prima dat definii de Rudolf Bayer n 1972 sub forma de arbori simetrici. Asemenea arborilor AVL, aceast structur este caracterizat de o complexitate a operaiei de cutare egal cu O(log n), n fiind numrul de noduri din arbore, datorit modului n care nodurile sunt plasate n mod simetric n subarborii stngi sau drepi. Spre deosebire de arborele AVL, n care principala caracteristic se determin pe baza gradului de echilibru al fiecrui nod, n structurile arborescente de tip Rosu & Negru, factorul cel mai important este dat de culoarea fiecrui nod: - fiecare nod are una dintre cele dou culori, rou sau negru; - nodul rdcin este ntotdeauna negru; - ambele noduri fiu ale unui nod printe rou sunt negre; un nod rou nu poate avea ca printe dect un nod negru; - toate drumurile de la rdcin la oricare din nodurile frunz conin acelai numr de noduri negre. Analiznd aceste caracteristici sunt derivate proprieti noi care s fie utilizate n implementarea algoritmilor sau care s evidenieze eficiena acestui tip de structur fa de un arbore binar de cutare: - n arborele Rou & Negru nu exist pe un drum dou noduri adiacente de culoare roie deoarece orice nod rou are ambii fii de culoare neagr; - dac se consider c cel mai scurt drum din arbore are numai noduri negre n numr de k, atunci cel mai lung drum din arbore are maxim dublu noduri, 2 * k; ipoteza este demonstrat pe baza faptului c toate drumurile din acest tip de structur au acelai numr de noduri negre, fapt care conduce la concluzia c drumul cel mai lung poate fi format doar din perechi de noduri adiacente de culori opuse, figura 14.23.
15 rou 3 negru 2 negru 18 27 23 negru negru rou

Figura 14.23 Structur arborescenta de tip Rou & Negru

Pentru a facilita implementarea operaiilor cu structuri arborescente de tip Rosu & Negru se propune o structur asociat nodului, clasa RNNode
class RNNod { int Info; bool Culoare; RNNod *st; RNNod *dr; RNNod *parinte; };

Elementele de tip RNNode includ pe lng atributele ntlnite la toate structurile arborescente binare: - informaia util; - cele dou legturi ctre nodurile fiu din stnga, respectiv, dreapta; i informaia ce descrie culoare nodului, precum i o legtur suplimentar ctre nodul printe. Aceast abordare contribuie la implementarea mult mai facil a operaiilor de inserare sau tergere, minimiznd n timp real efortul de a identifica nodul printe al nodului curent.

14.5 Operaii pe arbori Rou & Negru


Operaiile pe arborii Rou i Negru descrise, inserare i tergere, sunt realizate asemenea arborilor binari de cutare deoarece acest tip de arbore este o structur binar particular. Asigurarea caracteristicilor specifice acestui tip de structur arborescent este realizat printr-o serie de operaii auxiliare i complementare procesului de inserare sau tergere ce constau n rotiri sau modificri de culoare. Pentru a descrie metodele specifice operaiilor se definete ca nod bunic al nodului nou creat, nodul ce se gsete pe al doilea nivel superior fa de nodul analizat, figura 14.24. Se definete ca nod unchi al nodului analizat, al doilea nod fiu al nodului bunic.

15 nod printe 3 nod analizat 2 18

nod bunic nod unchi 23

27

Figura 14.24 Relaii ntre noduri Rou & Negru

Pentru a determina poziia acestor noduri particulare este utilizat atributul RNNod *parinte al fiecrui obiect de tip RNNod. De exemplu nodul bunic al nodului curent este determinat prin expresia NodCurent->parinte>parinte, iar nodul unchi este dat de NodCurent->parinte->parinte->st sau NodCurent->parinte->parinte->st n funcie de poziia acestuia relativ la nodul printe al nodului curent. Operaia de inserare este analizat prin prisma cazurilor particulare. Acestea sunt definite de contextul n care se gsete nodul nou creat i de situaiile de dezechilibru aprute. Fiecare nod nou creat i inserat n structura arborescent de tip Rou i Negru are culoarea iniial roie. Astfel se ncearc evitarea situaie n care este nclcat proprietatea c toate drumurile din arbore au acelai numr de noduri negre. Se consider arborele Rou & Negru vid n care se insereaz valoarea 43. prin inserare se obine structura arborescent din figura 14.25 ce trebuie reechilibrat prin modificarea culorii nodului rdcin n negru. Astfel nodul rdcin este negru.

reechilibrare prin modificare culoare 43 nod rou 43 nod negru

Figura 14.25 Arbore Rou & Negru cu un singur nod n arborele analizat se insereaz valorile 25 i 78. Nodurile nou create au culoare roie, figura 14.26 i nu este nclcat nici o proprietate a arborilor.

43

25

78

Figura 14.26 Arbore Rou & Negru echilibrat Se ia n considerare situaia n care se insereaz nodul cu valoarea 14. Nodul nou creat este rou, fapt care ncalc proprietile arborilor Rou & Negru, deoarece un nod rou are ntotdeauna un nod negru ca printe. Dac nodul este recolorat n negru atunci toate drumurile din arbore nu vor avea acelai numr de noduri negre. Situaia este analizat prin prisma nodului printe i a nodului unchi. Dac aceste dou noduri sunt roii atunci ele i schimb culoarea n negru, iar nodul bunic, printele celor dou noduri, devine negru, figura 14.27. Dac prin modificarea culorii nodului bunic, arborele este dezechilibrat atunci situaia este remediat n manier recursiv pn se ajunge la rdcina arborelui.

43

reechilibrare prin modificare culoare 78 25

43
dezechilibru

25

78

14
dezechilibru

14 nod bunic 43 nod printe 25 nod nou 14 nod unchi 78

Figura 14.27 Arbore Rou & Negru reechilibrat n cazul arborelui din figura 14.27, nodul rdcin devine negru la pasul urmtor, structura fiind reechilibrat. Se consider exemplul dat de inserarea valorii 17. Nodul nou are culoare roie, fapt ce ncalc proprietatea acestui tip de arbore, toate nodurile fiu ale unui nod rou sunt negre, figura 14.28.
43 nod bunic 25 nod printe 14 nod NULL 78

17 nod nou

dezechilibru

Figura 14.28 Arbore Rou & Negru dezechilibrat Reechilibrarea arborelui n aceast situaie este realizat printr-o dubl rotaie. ntr-o prim faz, se realizeaz o simpl rotaie la stnga n nodul printe. Ipoteza de lucru este definit de faptul c: - nodul printe are culoare roie, dar nodul unchi este fie negru, fie nod NULL; - nodul nou creat este fiu dreapta pentru nodul printe, care la rndul su este nod fiu stnga pentru nodul bunic. Rotaia este realizat asemenea arborilor AVL considernd pivot, nodul printe. Dup aceast prima rotaie se obine arborele din figura 14.29.

43 nod bunic 25 nod printe 14 nod NULL 17 nod printe nou 17 nod nou
dezechilibru

43 nod bunic 78 25 78

nod NULL

14
dezechilibru

Figura 14.29 Arbore Rou & Negru dezechilibrat Structura arborescent este dezechilibrat prin prisma aceleiai proprieti nclcate. Din acest motiv este necesar o a doua operaie de rotaie ce are ca pivot, nodul bunic. De data aceasta, rotaie se realizeaz la dreapta, avnd sens opus cu direcia nodului fiu fa de nodul printe. Ipoteza de lucru este definit de condiiile: - nodul printe are culoare roie, dar nodul unchi este fie negru, fie nod NULL; - noul nod printe este fiu stnga pentru nodul bunic i nodul nou inserat este fiu stnga pentru acesta. Rotaia descris n figura 14.30 este nsoit i de o recolorare a nodurilor, astfel nct nodul bunic devine rou i noul nod printe devine negru.
43 nod bunic 25 78 17 78 43

17 nod printe nou 14


dezechilibru

nod NULL

14

25 nod bunic vechi nod NULL

Figura 14.30 Arbore Rou & Negru reechilibrat n cazul n care, se insera valoarea 10 atunci erau atinse condiiile implementrii celei de a doua operaie de rotaie fiind evitat prima rotaie la stnga. Dac nodul nou are ca printe un nod de culoare roie i acesta este fiul din dreapta al nodului bunic, atunci situaia reprezint imaginea n oglind a cazului anterior. De exemplu, se insereaz valorile 89 i 95 n aceast ordine. Figura 14.31 descrie pii parcuri pentru reechilibrarea arborelui.

43 nod bunic 17 78 nod parinte 14 25 89 14 25 17

43

89

78

95

nod nou
dezechilibru

95

Figura 14.31 Reechilibrare arbore Rou & Negru Situaia descris anterior este condiionat de atingerea urmtoarelor condiii de lucru: - nodul printe are culoare roie, dar nodul unchi este fie negru, fie nod NULL; - nodul printe este fiu dreapta pentru nodul bunic i nodul nou inserat este fiu dreapta pentru acesta. n cazul n care ultima condiie nu este ndeplinit, noul nod fiind fiu stnga, situaia este ajustat prin operaia de rotire la dreapta n nodul printe. Operaia de tergere n arbori Rou i Negru completeaz procesul ntlnit la arborii binari de cutare prin operaii specifice de recolorare sau rotire a nodurilor astfel nct s fie pstrate caracteristicile acestei structuri arborescente. n cazul n care nodul de ters are dou noduri fiu atunci acesta este nlocuit de nodul cu valoarea cea mai mare din subarborele stng sau de nodul cu valoarea cea mai mic din subarborele drept. Copierea de valoarea este nsoit de pstrarea culorii nodului ters astfel nct s nu fie afectat arborele. Oricare variant se alege, nodul care va nlocui nodul de ters este la rndul su eliminat din structura arborescent. Acesta este fie nod frunz, fie are maxim un fiu. De exemplu, se terge nodul cu valoarea 43 din arborele descris n figura 14.32.
nod de ters

43

78
nlocuire cu cel mai mic nod din subarborele drept

Pstrare culoare

17

89

17

89

14

25

78

95

14

25

95

Figura 14.32 tergere nod din arbore Rou & Negru Prin prisma exemplului anterior, problemele aprute la tergerea unui nod dintr-un arbore Rou i Negru sunt concentrate n cazurile de tergerea unui nod care are maxim un fiu. Dac nodul de ters este de culoare roie, figura 14.30, atunci nodul su fiu este de culoare neagr, aceasta fiind o caracteristic a arborilor Rou i Negru. tergerea nodului implic n aceast situaie nlocuirea sa cu nodul

fiu. Arborele este n continuare Rou i Negru deoarece tergerea unui nod rou nu are implicaii asupra numrului de noduri negre de pe fiecare drum.
43
nod de ters nlocuire cu unicul fiu al nodului de ters

43

17

89

14

89

14

78

15

78

15

Figura 14.33 Cazul 1 de tergere nod din arbore Rou & Negru Dac nodul ters este de culoare neagr, iar fiul su este de culoare roie, figura 14.34, atunci arborele devine dezechilibrat pe drumul care trece prin aceast zon deoarece numrul de noduri negre este mai mic cu unul. Reechilibrarea structurii arborescente se face n aceast situaie prin recolorarea n negru a nodului fiu. Astfel este refcut numrul de noduri negre.
43
nod de ters nlocuire cu unicul fiu al nodului de ters

43

17

79

14
recolorat in negru

79

14

54

83

15

54

83

15

48

59

80

48

59

80

Figura 14.34 Cazul 2 de tergere nod din arbore Rou & Negru Situaiile complexe aprute la tergerea unui nod dintr-un arbore de tip Rou i Negru sunt apar n cazul n care nodul de ters i fiul su sunt de culoare neagr. Prin eliminarea nodului, arborele devine dezechilibrat deoarece o parte din drumuri conin cu un nod negru mai puin. Spre deosebire de cazurile prezentate anterior, nu mai este posibil refacerea numrului de noduri negre prin recolorarea fiului deoarece acesta are deja culoarea neagr. Reechilibrarea arborelui este realizat printr-un numr fix de operaii de rotire sau recolorare. Pentru a descrie aceste cazuri particulare de dezechilibru i soluiile asociate, se fac o serie de notaii care s ajute nelegerea operaiilor, figura 14.35. Se noteaz cu: - P, nodul printe al nodului de ters; - F, nodul fiu al nodului de ters; - B, nodul bunic al nodului de ters; acest nod este nodul printe al nodului P; - U, nodul unchi al nodului de ters; acest nod este reprezentat de al doilea fiu al nodului B;

N1 nodul nepot al nodului de ters; este reprezentat de fiul din stnga al nodului unchi; N2 nodul nepot al nodului de ters; este reprezentat de fiul din dreapta al nodului unchi;
B nod printe P

32

nod bunic

nod unchi

25
nod nepot

79

nod de ters

14

N1

54

N2

89

nod fiu F

17

45

58

81

Figura 14.35 Arbore Rou & Negru Urmtorul caz analizat este dat de figura 14.36 n care nodul cu valoarea 25 este ters. Situaia este descris de ipotezele: - nodul de ters este negru; - unicul fiu al nodului de ters este negru; - nodul unchi al nodului de ters este negru; - nodul printe este negru; - nodurile nepoi sunt negre.
B P nod de ters B dezechilibru U F P

32

32
U

25

79

14

79

14

N1

54

N2

89

10

17

N1

54

N2

89

10

17

45

58

81

45

58

81

Figura 14.36 Cazul 3 de tergere nod din arbore Rou & Negru Prin tergerea nodului cu valoarea 25, arborele sau subarborele analizat ce are rdcin pe nodul cu valoarea 32 este dezechilibrat la dreapta deoarece drumurile care pornesc din rdcin i continu pe partea stng au cu un nod negru mai puin. Reechilibrarea arborelui se realizeaz prin modificarea culorii nodului unchi, valoarea 79, n rou, figura 14.37. Astfel, este redus cu unu numrul de noduri negre din drumurile ce pornesc din rdcina 32.

B dezechilibru F P

B modificare culoare nod unchi U P

32

32
U

14

79

14

79

10

17

N1

54

N2

89

10

17

N1

54

N2

89

45

58

81

45

58

81

Figura 14.37 Soluie de reechilibrare caz 3 pentru arbore Rou & Negru n cazul n care, nodul cu valoarea 32 reprezint rdcina unui subarbore, analiza se continu n sus pn cnd se atinge rdcina arborelui sau pn cnd arborele este reechilibrat pe baza unei soluii din cele descrise. Al patrulea caz de tergere a unui nod dintr-un arbore Rou i Negru ia n considerare situaia descris n figura 14.38: - nodul de ters este negru; - unicul fiu al nodului de ters este negru; - nodul unchi al nodului de ters este negru; - nodul printe este rou; - nodurile nepoi sunt negre.
B P nod de ters B dezechilibru U F P

22

22
U

15

69

69

N1

54

N2

89

N1

54

N2

89

45

58

81

45

58

81

Figura 14.38 Cazul 4 de tergere nod din arbore Rou & Negru Asemenea cazului anterior, arborele i pierde calitatea de a fi Rou i Negru n urma tergerii deoarece nu toate drumurile de la rdcin la nodurile frunz au acelai numr de noduri negre. Reechilibrarea este realizat prin interschimbarea culorilor nodului printe i nodului unchi, figura 14.39.

B dezechilibru F P

B P U

22

22
U

69

69

N1

54

N2

89

N1

54

N2

89

45

58

81

45

58

81

Figura 14.39 Soluie de reechilibrare caz 4 pentru arbore Rou & Negru n situaia n care arborele din figura 14.34 reprezint un subarbore atunci soluia de reechilibrare prezentat are doar efecte locale, deoarece lungimea msurat n numr de noduri negre a tuturor drumurilor din acest subarbore este mai mic cu unu fa de situaia iniial. Din acest motiv, reechilibrarea se continu recursiv ctre rdcina arborelui. Cazul al cincilea de tergere a unui nod ia n considerare ipotezele descrise n figura 14.40: - nodul de ters este negru; - unicul fiu al nodului de ters este negru; - nodul unchi al nodului de ters este rou; - nodul printe este negru; - nodurile nepoi sunt negre.
B P nod de ters B dezechilibru U F P

32

32
U

25

79

14

79

14

N1

54

N2

89

10

17

N1

54

N2

89

10

17

45

58

81

45

58

81

Figura 14.40 Cazul 5 de tergere nod din arbore Rou & Negru Reechilibrarea arborelui pentru cazul 5 de dezechilibru se realizeaz prin interschimbarea culorilor nodului unchi i nodului printe, urmat de o rotaie la stnga n nodul printe, figura 14.41.

B P

B (1) U interschimb culori (1) + rotire (2) U

32

79

14

(2) N1

79

dezechilibru

32

N2

89

10

17

54

N2

89

14

N1

54

81

45

58

81

10

17

45

58

Figura 14.41 Soluie de reechilibrare caz 5 pentru arbore Rou & Negru Analiznd figura 14.41 se observ c soluia cazului 5 nu conduce la reechilibrarea total a arborelui. Zona de dezechilibru este modificat astfel nct s poat fi reechilibrat ntr-un numr finit de pai. Aceast este analizat prin prisma cazului patru care a fost descris sau prin intermediul cazurilor ase i apte. De exemplu, arborele obinut n figura 14.41 este reechilibrat, n figura 14.42 prin intermediul soluie oferite n cazul patru, interschimbnd culorile nodului cu valoare 32 i nodului cu valoarea 54.
B U dezechilibru B Interschimbare culori U

79

79

32

N2

89
F

32

N2

89

14

N1

54

81

14

N1

54

81

10

17

45

58

10

17

45

58

Figura 14.42 Reechilibrare arbore Rou & Negru din figura 14.41 Urmtoarele dou cazuri analizeaz culoarea nodurilor nepoi lund n calcul situaii derivate din cazul patru. Cazul ase, descris n figura 14.43, este definit de urmtoarele ipoteze: - nodul de ters este negru; - unicul fiu al nodului de ters este negru; - nodul unchi al nodului de ters este negru; - nodul printe este rou sau negru; - nodul nepot N1 este rou; - nodul nepot N2 este negru.

B P nod de ters

B dezechilibru U F P

22

22
U

15

69

69

N1

54

N2

89

N1

54

N2

89

45

58

81

45

58

81

Figura 14.43 Cazul 6 de tergere nod din arbore Rou & Negru Reechilibrarea arborelui din figura 14.43 este realizat prin: - interschimbarea culorilor nodului printe i a nodului unchi; - rotirea subarborelui cu rdcin n nodul unchi la dreapta.
B dezechilibru F P B interschimb culori (1) + rotire (2) U F N2 P dezechilibru

22

22

(1) N1

69

N1

54
U

54

(2)

89

45

69

45

58

81

58

N2

89

81

Figura 14.44 Soluie de reechilibrare caz 6 pentru arbore Rou & Negru Rezultatul obinut n urma operaiei de schimbare a culorii i de rotire nu conduce la reechilibrarea arborelui. Cu toate acestea, noua form a subarborelui permite reechilibrarea la pasul urmtor, deoarece situaia curent descrie cazul apte . Cazul ase, descris n figura 14.45, este definit de urmtoarele ipoteze: - nodul de ters este negru; - unicul fiu al nodului de ters este negru; - nodul unchi al nodului de ters este negru; - nodul printe este rou sau negru; - nodul nepot N1 este rou sau negru; - nodul nepot N2 este rou.

B P nod de ters

B dezechilibru U F P

22

22
U

15

69

69

N1

54

N2

89

N1

54

N2

89

45

58

81

45

58

81

Figura 14.45 Cazul 7 de tergere nod din arbore Rou & Negru Reechilibrarea situaie descrise n figura 14.46 se realizeaz prin: - interschimbare culoare nod printe cu nodul unchi; - rotire la stnga a arborelui n nodul printe; - modificare culoare nepot N2 n negru.
B dezechilibru F P B interschimb culori (1) + rotire (2)+ schimbare culoare(3) U P

22

(1)

69

(2) N1

69
(3)

22

N2 N1

89

54

N2

89

54

81

45

58

81

45

58

Figura 14.46 Soluie de reechilibrare caz 7 pentru arbore Rou & Negru Figura 14.46 prezint rezultatul obinut n urma reechilibrrii. Se observ eliminarea dezechilibrului din acest arbore sau subarbore. Pentru exemplele analizate n acest capitol s-a considerat c nodul de ters se gsete n partea stng a nodului printe. Pentru situaia opus, soluiile descrise au aceleai efect dac sufer mici modificri prin prisma noului reper de vizualizare a arborelui. De asemenea, n exemplele prezentate reechilibrarea arborelui are un caracter local pentru a descrie tehnicile de reechilibrare, ns realizare unei aplicaii trebuie s implementeze secvene care s parcurg arborele de jos n sus, de la poziia nodului de ters ctre rdcina arborelui i care s reechilibreze toat structura.

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