AVL stabla: rotacije, umetanje, brisanje sa C++ Primjer
ล to su AVL stabla?
AVL stabla su binarna stabla pretraลพivanja u kojima je razlika izmeฤu visine lijevog i desnog podstabla ili -1, 0 ili +1.
AVL stabla se takoฤer nazivaju samobalansirajuฤim binarnim stablom pretraลพivanja. Ova stabla pomaลพu u odrลพavanju logaritamskog vremena pretraลพivanja. Ime je dobio po svojim izumiteljima (AVL) Adelsonu, Velskyju i Landisu.
Kako radi AVL stablo?
Kako bismo bolje razumjeli potrebu za AVL stablima, pogledajmo neke nedostatke jednostavnih stabala binarnog pretraลพivanja.
Razmotrite sljedeฤe kljuฤeve umetnute danim redoslijedom u stablo binarnog pretraลพivanja.

Visina stabla linearno raste kada umetnemo kljuฤeve rastuฤim redoslijedom njihove vrijednosti. Dakle, operacija pretraลพivanja, u najgorem sluฤaju, traje O(n).
Za traลพenje elementa potrebno je linearno vrijeme; stoga nema koristi od koriลกtenja Stablo binarnog pretraลพivanja struktura. S druge strane, ako je visina stabla uravnoteลพena, dobivamo bolje vrijeme traลพenja.
Pogledajmo sada iste kljuฤeve, ali umetnute drugaฤijim redoslijedom.
Ovdje su kljuฤevi isti, ali buduฤi da su umetnuti drugaฤijim redoslijedom, zauzimaju razliฤite poloลพaje, a visina stabla ostaje uravnoteลพena. Stoga pretraลพivanje neฤe trajati viลกe od O(log n) za bilo koji element stabla. Sada je oฤito da ako se umetanje pravilno izvede, visina stabla moลพe biti uravnoteลพena.
U AVL stablima provjeravamo visinu stabla tijekom operacije umetanja. Izmjene su napravljene kako bi se odrลพala uravnoteลพena visina bez naruลกavanja osnovnih svojstava stabla binarnog pretraลพivanja.
Faktor ravnoteลพe u AVL stablima
Faktor ravnoteลพe (BF) temeljni je atribut svakog ฤvora u AVL stablima koji pomaลพe u praฤenju visine stabla.
Svojstva faktora ravnoteลพe
- Faktor ravnoteลพe poznat je kao razlika izmeฤu visine lijevog podstabla i desnog podstabla.
- Faktor ravnoteลพe (ฤvor) = visina (ฤvor->lijevo) โ visina (ฤvor->desno)
- Dopuลกtene vrijednosti BF su โ1, 0 i +1.
- Vrijednost โ1 oznaฤava da desno pod-stablo sadrลพi jedno dodatno, tj. da je stablo desno teลกko.
- Vrijednost +1 oznaฤava da lijevo podstablo sadrลพi jedno dodatno, tj. da je stablo lijevo teลกko.
- Vrijednost 0 pokazuje da stablo ukljuฤuje jednake ฤvorove sa svake strane, tj. da je stablo savrลกeno uravnoteลพeno.
AVL rotacije
Kako bi se AVL stablo samo uravnoteลพilo, prilikom umetanja ili brisanja ฤvora iz stabla, izvode se rotacije.
Izvodimo sljedeฤu LL rotaciju, RR rotaciju, LR rotaciju i RL rotaciju.
- Lijevo โ Lijeva rotacija
- Desno โ Desna rotacija
- Rotacija desno โ lijevo
- Rotacija lijevo โ desno
Lijevo โ Lijeva rotacija
Ova rotacija se izvodi kada se novi ฤvor umetne u lijevo dijete lijevog podstabla.
Izvodi se jedna desna rotacija. Ova vrsta rotacije prepoznaje se kada ฤvor ima faktor ravnoteลพe +2, a njegov lijevi potomak ima faktor ravnoteลพe +1.
Desno โ Desna rotacija
Ova rotacija se izvodi kada se novi ฤvor umetne u desno dijete desnog podstabla.
Izvodi se jedna rotacija ulijevo. Ova vrsta rotacije identificira se kada ฤvor ima faktor ravnoteลพe -2, a njegov desni potomak ima faktor ravnoteลพe -1.
Rotacija desno โ lijevo
Ova rotacija se izvodi kada se novi ฤvor umetne u desno dijete lijevog podstabla.
Ova se rotacija izvodi kada ฤvor ima faktor ravnoteลพe kao โ2, a njegov desni dijete ima faktor ravnoteลพe kao +1.
Rotacija lijevo โ desno
Ova rotacija se izvodi kada se novi ฤvor umetne u lijevo dijete desnog podstabla.
Ova rotacija se izvodi kada ฤvor ima faktor ravnoteลพe kao +2, a njegov lijevi dijete ima faktor ravnoteลพe kao -1.
Umetanje u AVL stabla
Operacija umetanja gotovo je ista kao kod jednostavnih stabala binarnog pretraลพivanja. Nakon svakog umetanja balansiramo visinu stabla. Operacija umetanja traje O(log n) najgore vremenske sloลพenosti.
Korak 1: Umetnite ฤvor u AVL stablo koristeฤi isti algoritam umetanja kao BST. U gornjem primjeru umetnite 160.
Korak 2: Nakon dodavanja ฤvora, aลพurira se faktor ravnoteลพe svakog ฤvora. Nakon umetanja 160, faktor ravnoteลพe svakog ฤvora se aลพurira.
Korak 3: Sada provjerite krลกi li bilo koji ฤvor raspon faktora ravnoteลพe ako je faktor ravnoteลพe naruลกen, zatim izvedite rotacije koristeฤi donji sluฤaj. U gornjem primjeru, faktor ravnoteลพe od 350 je naruลกen i tu postaje primjenjiv sluฤaj 1, izvodimo LL rotaciju i stablo je ponovno uravnoteลพeno.
- Ako je BF(ฤvor) = +2 i BF(ฤvor -> lijevo dijete) = +1, izvrลกite LL rotaciju.
- Ako je BF(ฤvor) = -2 i BF(ฤvor -> desno dijete) = 1, izvedite RR rotaciju.
- Ako je BF(ฤvor) = -2 i BF(ฤvor -> desno dijete) = +1, izvrลกite RL rotaciju.
- Ako je BF(ฤvor) = +2 i BF(ฤvor -> lijevo dijete) = -1, izvrลกite LR rotaciju.
Brisanje u AVL stablima
Brisanje je takoฤer vrlo jednostavno. Briลกemo koristeฤi istu logiku kao u jednostavnim stablima binarnog pretraลพivanja. Nakon brisanja, restrukturiramo stablo, ako je potrebno, kako bismo zadrลพali njegovu uravnoteลพenu visinu.
Korak 1: Pronaฤite element u stablu.
Korak 2: Izbriลกite ฤvor u skladu s BST brisanjem.
Korak 3: Moguฤa su dva sluฤaja: -
Sluฤaj 1: Brisanje iz desnog podstabla.
- 1A. Ako je BF(ฤvor) = +2 i BF(ฤvor -> lijevo dijete) = +1, izvrลกite LL rotaciju.
- 1B. Ako je BF(ฤvor) = +2 i BF(ฤvor -> lijevo dijete) = -1, izvrลกite LR rotaciju.
- 1C. Ako je BF(ฤvor) = +2 i BF(ฤvor -> lijevo dijete) = 0, izvedite LL rotaciju.
Sluฤaj 2: Brisanje iz lijevog podstabla.
- 2A. Ako je BF(ฤvor) = -2 i BF(ฤvor -> desno dijete) = -1, izvrลกite RR rotaciju.
- 2B. Ako je BF(ฤvor) = -2 i BF(ฤvor -> desno dijete) = +1, izvrลกite RL rotaciju.
- 2C. Ako je BF(ฤvor) = -2 i BF(ฤvor -> desno dijete) = 0, izvedite RR rotaciju.
C++ Primjer AVL stabala
Ispod je C++ koji implementira AVL stabla:
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
struct node {
struct node *left;
int data;
int height;
struct node *right;
};
class AVL
{
private:
public:
struct node * root;
AVL(){
this->root = NULL;
}
int calheight(struct node *p){
if(p->left && p->right){
if (p->left->height < p->right->height)
return p->right->height + 1;
else return p->left->height + 1;
}
else if(p->left && p->right == NULL){
return p->left->height + 1;
}
else if(p->left ==NULL && p->right){
return p->right->height + 1;
}
return 0;
}
int bf(struct node *n){
if(n->left && n->right){
return n->left->height - n->right->height;
}
else if(n->left && n->right == NULL){
return n->left->height;
}
else if(n->left== NULL && n->right ){
return -n->right->height;
}
}
struct node * llrotation(struct node *n){
struct node *p;
struct node *tp;
p = n;
tp = p->left;
p->left = tp->right;
tp->right = p;
return tp;
}
struct node * rrrotation(struct node *n){
struct node *p;
struct node *tp;
p = n;
tp = p->right;
p->right = tp->left;
tp->left = p;
return tp;
}
struct node * rlrotation(struct node *n){
struct node *p;
struct node *tp;
struct node *tp2;
p = n;
tp = p->right;
tp2 =p->right->left;
p -> right = tp2->left;
tp ->left = tp2->right;
tp2 ->left = p;
tp2->right = tp;
return tp2;
}
struct node * lrrotation(struct node *n){
struct node *p;
struct node *tp;
struct node *tp2;
p = n;
tp = p->left;
tp2 =p->left->right;
p -> left = tp2->right;
tp ->right = tp2->left;
tp2 ->right = p;
tp2->left = tp;
return tp2;
}
struct node* insert(struct node *r,int data){
if(r==NULL){
struct node *n;
n = new struct node;
n->data = data;
r = n;
r->left = r->right = NULL;
r->height = 1;
return r;
}
else{
if(data < r->data)
r->left = insert(r->left,data);
else
r->right = insert(r->right,data);
}
r->height = calheight(r);
if(bf(r)==2 && bf(r->left)==1){
r = llrotation(r);
}
else if(bf(r)==-2 && bf(r->right)==-1){
r = rrrotation(r);
}
else if(bf(r)==-2 && bf(r->right)==1){
r = rlrotation(r);
}
else if(bf(r)==2 && bf(r->left)==-1){
r = lrrotation(r);
}
return r;
}
void levelorder_newline(){
if (this->root == NULL){
cout<<"\n"<<"Empty tree"<<"\n";
return;
}
levelorder_newline(this->root);
}
void levelorder_newline(struct node *v){
queue <struct node *> q;
struct node *cur;
q.push(v);
q.push(NULL);
while(!q.empty()){
cur = q.front();
q.pop();
if(cur == NULL && q.size()!=0){
cout<<"\n";
q.push(NULL);
continue;
}
if(cur!=NULL){
cout<<" "<<cur->data;
if (cur->left!=NULL){
q.push(cur->left);
}
if (cur->right!=NULL){
q.push(cur->right);
}
}
}
}
struct node * deleteNode(struct node *p,int data){
if(p->left == NULL && p->right == NULL){
if(p==this->root)
this->root = NULL;
delete p;
return NULL;
}
struct node *t;
struct node *q;
if(p->data < data){
p->right = deleteNode(p->right,data);
}
else if(p->data > data){
p->left = deleteNode(p->left,data);
}
else{
if(p->left != NULL){
q = inpre(p->left);
p->data = q->data;
p->left=deleteNode(p->left,q->data);
}
else{
q = insuc(p->right);
p->data = q->data;
p->right = deleteNode(p->right,q->data);
}
}
if(bf(p)==2 && bf(p->left)==1){ p = llrotation(p); }
else if(bf(p)==2 && bf(p->left)==-1){ p = lrrotation(p); }
else if(bf(p)==2 && bf(p->left)==0){ p = llrotation(p); }
else if(bf(p)==-2 && bf(p->right)==-1){ p = rrrotation(p); }
else if(bf(p)==-2 && bf(p->right)==1){ p = rlrotation(p); }
else if(bf(p)==-2 && bf(p->right)==0){ p = llrotation(p); }
return p;
}
struct node* inpre(struct node* p){
while(p->right!=NULL)
p = p->right;
return p;
}
struct node* insuc(struct node* p){
while(p->left!=NULL)
p = p->left;
return p;
}
~AVL(){
}
};
int main(){
AVL b;
int c,x;
do{
cout<<"\n1.Display levelorder on newline";
cout<<"\n2.Insert";
cout<<"\n3.Delete\n";
cout<<"\n0.Exit\n";
cout<<"\nChoice: ";
cin>>c;
switch (c)
{
case 1:
b.levelorder_newline();
// to print the tree in level order
break;
case 2:
cout<<"\nEnter no. ";
cin>>x;
b.root = b.insert(b.root,x);
break;
case 3:
cout<<"\nWhat to delete? ";
cin>>x;
b.root = b.deleteNode(b.root,x);
break;
case 0:
break;
}
} while(c!=0);
}
Izvrลกeni primjer gornjeg koda:
- Kopirajte gornji kod i zalijepite u โavl.cppโ.
- Sastavite kod:
g++ avl.cpp -o run
- Pokrenite kod.
./run
Prednosti AVL stabala
- Visina AVL stabla uvijek je uravnoteลพena. Visina nikada ne prelazi log N, gdje je N ukupan broj ฤvorova u stablu.
- Omoguฤuje bolju sloลพenost vremena pretraลพivanja u usporedbi s jednostavnim stablima binarnog pretraลพivanja.
- AVL stabla imaju sposobnost samobalansiranja.
Rezime
- AVL stabla su binarna stabla pretraลพivanja koja se sama balansiraju.
- Faktor ravnoteลพe temeljni je atribut AVL stabala
- Faktor ravnoteลพe ฤvora definiran je kao razlika izmeฤu visine lijevog i desnog podstabla tog ฤvora.
- Vaลพeฤe vrijednosti faktora ravnoteลพe su -1, 0 i +1.
- Operacije umetanja i brisanja zahtijevaju izvoฤenje rotacija nakon naruลกavanja faktora ravnoteลพe.
- Vremenska sloลพenost operacije umetanja, brisanja i pretraลพivanja je O(log N).
- AVL stabla slijede sva svojstva stabala binarnog pretraลพivanja.
- Lijevo podstablo ima ฤvorove koji su manji od korijenskog ฤvora. Desno podstablo ima ฤvorove koji su uvijek veฤi od korijenskog ฤvora.
- AVL stabla se koriste tamo gdje je operacija pretraลพivanja ฤeลกฤa u usporedbi s operacijama umetanja i brisanja.







