You are on page 1of 4

AVL

Arborii AVL (Adelson-Velski, Landis) sunt arbori binari de cutare n care fiecare subarbore este
echilibrat n nltime. Pentru a recunoaste rapid o dezechilibrare a arborelui s-a introdus n fiecare
nod un cmp suplimentar, care s arate fie nltimea nodului, fie diferenta dintre nltimile celor doi
subarbori pentru acel nod ( 1, 0, 1 pentru noduri echilibrate si 2 sau +2 la producerea unui
dezechilibru).+

La adugarea unui nou nod (ca frunz) factorul de echilibru al unui nod interior se poate modifica la
2 (adugare la subarborele stnga) sau la +2 (adugare la subarborele dreapta), ceea ce va face
necesar modificarea structurii arborelui.

Reechilibrarea se face prin rotatii simple sau duble, nsotite de recalcularea nltimii fiecrui nod
ntlnit parcurgnd arborele de jos n sus, spre rdcin.

Putem generaliza cazurile anterioare astfel:

- Insertia n subarborele dreapta al unui fiu dreapta necesit o rotatie simpl la stnga

- Insertia n subarborele stnga al unui fiu stnga necesit o rotatie simpl la dreapta

- Insertia n subarborele stnga al unui fiu dreapta necesit o rotatie dubl la stnga

- Insertia n subarborele dreapta al unui fiu stnga necesit o rotatie dubl la dreapta

Inltimea maxim a unui arbore AVL este 1.44*log(n), deci n cazul cel mai ru cutarea ntr-un
arbore AVL nu necesit mai mult de 44% comparatii fat de cele necesare ntr-un arbore perfect
echilibrat. In medie, este necesar o rotatie (simpl sau dubl) cam la 46,5% din adugri si este
suficient o singur rotatie pentru refacere.

Implementarea care urmeaz memoreaz n fiecare nod din arbore nltimea sa, adic nltimea
subarborelui cu rdcina n acel nod. Un nod vid are nltimea 1, iar un nod frunz are nltimea 0.

typedef struct tnod {

int val; // valoare din nod

int h; // inaltime nod

struct tnod *st, *dr; // adrese succesori

} tnod;

// determina inaltime nod cu adresa p

int ht (tnod * p) { return p==NULL? -1: p-> h; }

Operatiile de rotatie simpl recalculeaz n plus si nltimea:

// rotatie simpla la dreapta (radacina)

void rotR( tnod * & r ) {


tnod *f = r ->st; // fiu stanga

r ->st = f-> dr;

f ->dr = r; // r devine fiu dreapta al lui f

r->h = max( ht(r-> st), ht(r-> dr))+1; // inaltime r dupa rotatie

f ->h=max( ht(f-> st),r-> h)+1; // inaltime f dupa rotatie

r = f;

// rotatie simpla la stanga (radacina)

void rotL( tnod * & r ) {

tnod *f = r-> dr; // fiu dreapta

r ->dr = f ->st;

f-> st = r; // r devine fiu stanga al lui f

r ->h = max( ht(r-> st), ht(r-> dr))+1; // inaltime r dupa rotatie

f-> h=max( ht(f-> dr),r-> h)+1;

r = f;

Pentru arborii AVL sunt necesare si urmtoarele rotatii duble:

// rotatie dubla la stanga (RL)

void rotRL ( tnod * & p ){

rotR ( p ->dr ); // rotatie fiu dreapta la dreapta

rotL ( p ); // si apoi rotatie p la stanga

// rotatie dubla la dreapta (LR)

void rotLR ( tnod * & p ) {

rotL ( p ->st ); // rotatie fiu stanga la stanga

rotR ( p ); // si apoi rotatie p la dreapta }


Exemplu de functie recursiv pentru adugarea unei noi valori la un arbore AVL :

// adauga x la arbore AVL cu radacina r

void addFix ( tnod * & r, int x ) {

if ( r == NULL ) { // daca arbore vid

r = (tnod*) malloc(sizeof(tnod)); // atunci se creeaza radacina r

r ->val=x;

r-> st = r ->dr =NULL;

r-> h = 0; // inaltime nod unic

return;

if (x==r val) // daca x exista deja in arbore

return; // atunci nu se mai adauga

if( x < r val ) { // daca x este mai mic

addFix ( r-> st,x ); // atunci se adauga in subarbore stanga

if( ht ( r ->st ) ht ( r-> dr ) == 2 ) // daca subarbore dezechilibrat

if( x < r ->st-> val ) // daca x mai mic ca fiul stanga

rotR( r ); // rotatie dreapta r (radacina subarbore)

else // daca x mai mare ca fiul stanga

rotLR ( r ); // atunci dubla rotatie la dreapta r

else { // daca x este mai mare

addFix ( r ->dr,x ); // atunci se adauga la subarborele dreapta

if( ht ( r ->dr ) ht ( r-> st ) == 2 ) // daca subarbore dezechilibrat

if( x > r ->dr ->val ) // daca x mai mare ca fiul dreapta

rotL ( r ); // atunci rotatie stanga r

else // daca x mai mic ca fiul dreapta

rotRL ( r ); // atunci dubla rotatie la stanga


}

r-> h = max( ht ( r-> st ), ht ( r-> dr ) ) + 1; // recalculeaza inaltime nod r

Arborii AVL reprezinta o alternativa putin costisitoare la arborii binari obisnuiti. Cu pretul unor
reechilibrari suplimentare si fara a modifica semnificativ performanta insertiei si suprimarii cheilor
(celelalte operatii ramanand nemodificate), proprietatea de echilibru AVL a unui arbore binar
ordonat duce la cautari mult mai rapide decat in cazul unui arbore binar ordonat obisnuit, datorita
inaltimii mai mici

S-a demonstrat ca un arbore echilibrat AVL va avea intotdeauna inaltimea cuprinsa intre [log2N+1] si
[1,43log2N+1], unde N reprezinta numarul de chei din arbore si [x] este partea intreaga a lui x Spre
comparatie, un arbore binar ordonat perfect echilibrat va avea intotdeauna inaltimea egala cu
[log2N+1] dar a-l mentine perfect echilibrat este mult mai costisitor (ca timp) decat in cazul arborilor
AVL .De asemenea, un arbore binar ordonat obisnuit va avea inaltimea cuprinsa intre [log2N+1] si N,
deci poate ajunge la inaltimi mult mai mari decat un arbore AVL cu aceleasi chei

You might also like