Arbori AVL in C/C++
Un mic demo care lucreaza cu arbori AVL. Programul este scris in C++ (foloseste clase si alocarea dinamica a memoriei)
demo2.cpp
// demo2.cpp
#include <iostream>
#include <fstream>
#include "AVL.h"
using namespace std;
bool CitesteFisier(AVL &arb)
{
ifstream fin("noduri.txt", ios::in);
if(fin.fail())
return false;
// citim
int cheie;
while(!fin.eof())
{
fin>>cheie;
cout<<cheie<<", ";
arb.Adauga(cheie);
}
fin.close();
return true;
}
void main()
{
AVL arb;
int cheie;
char opt;
do
{
cout<<"C - initializeaza arborele AVL\n";
cout<<"I - insereaza un nod cu cheia precizata\n";
cout<<"S - suprima un nod cu o cheie precizata\n";
cout<<"V - vizualizeaza arborele pe niveluri\n";
cout<<"P - determina raportul intre numarul de reechilibrari si numarul de insertii\n";
cout<<"X - terminare\n";
cout<<"optiunea: ";
cin>>opt;
switch(opt)
{
case 'c':
arb.StergeArbore();
break;
case 'i':
cout<<"cheie: "; cin>>cheie;
arb.Adauga(cheie);
break;
case 's':
cout<<"cheie: "; cin>>cheie;
arb.StergeNod(cheie);
break;
case 'v':
arb.Nivele();
break;
case 'p':
arb.StergeArbore();
cout<<"noduri: ";
CitesteFisier(arb);
cout<<endl;
arb.Statistici();
cout<<endl;
break;
case 'x':
cout<<"iesire din program\n";
break;
default:
cout<<"optiunea invalida\n";
}
cout<<endl;
}
while(opt != 'x');
}
AVL.h
// fisierul AVL.h
#pragma once
#include <stdlib.h>
#include <iostream>
using namespace std;
typedef struct Node
{
int cheie, h;
struct Node *st, *dr;
} Node;
class AVL
{
private:
int nrIns, nrEch, nrNoduri;
Node *rad, *NIL;
Node* Sterge(Node *nod, int cheie);
Node* Insereaza(Node *n, int cheie);
bool Cauta(Node *n, int cheie);
Node* Balance(Node *n);
Node* RotDr(Node *n);
Node* RotSt(Node *n);
void DetH(Node *n);
void StergeArbore(Node *n);
public:
AVL(void);
~AVL(void) { StergeArbore(); }
void Adauga(int cheie) { rad = Insereaza(rad, cheie); }
void StergeNod(int cheie) { rad = Sterge(rad, cheie); }
void StergeArbore() { StergeArbore(rad); rad = NIL; nrEch = nrIns = nrNoduri = 0; }
void Statistici() { cout<<"insertii: "<<nrIns<<", echilibrari: "<<nrEch<<endl; }
void Nivele();
};
AVL.cpp
// fisierul AVL.cpp
#include "AVL.h"
AVL::AVL(void)
{
nrEch = nrIns = nrNoduri = 0;
rad = NIL = new Node;
NIL->cheie = NIL->h = 0;
NIL->st = NIL->dr = NULL;
}
void AVL::DetH(Node *n)
{
if(n->st->h > n->dr->h)
n->h = 1 + n->st->h;
else
n->h = 1 + n->dr->h;
}
Node* AVL::RotSt(Node *n)
{
Node *t = n->st;
n->st = t->dr;
t->dr = n;
DetH(n);
DetH(t);
return t;
}
Node* AVL::RotDr(Node *n)
{
Node *t = n->dr;
n->dr = t->st;
t->st = n;
DetH(n);
DetH(t);
return t;
}
Node* AVL::Balance(Node *n)
{
DetH(n);
if (n->st->h > n->dr->h + 1)
{
nrEch++; // nr ech
if (n->st->dr->h > n->st->st->h)
n->st = RotDr(n->st);
n = RotSt(n);
}
else if (n->dr->h > n->st->h + 1)
{
nrEch++; // nr ech
if (n->dr->st->h > n->dr->dr->h)
n->dr = RotSt(n->dr);
n = RotDr(n);
}
return n;
}
Node* AVL::Insereaza(Node *n, int cheie)
{
if (n == NIL)
{
nrIns++; // nr ins
nrNoduri++; // nr nod
n = new Node;
n->cheie = cheie;
n->h = 1;
n->st = n->dr = NIL;
return n;
}
if (cheie < n->cheie)
n->st = Insereaza(n->st, cheie);
else
n->dr = Insereaza(n->dr, cheie);
return Balance(n);
}
Node* AVL::Sterge(Node *n, int cheie)
{
Node *t;
if(n == NIL)
return n;
if(n->cheie == cheie)
{
if (n->st == NIL || n->dr == NIL)
{
t = n->st;
if(t == NIL)
n->dr;
else
n->st;
nrNoduri--; // nr nod
delete n;
return t;
}
else
{
for (t = n->dr; t->st != NIL; t = t->st);
n->cheie = t->cheie;
n->dr = Sterge(n->dr, t->cheie);
return Balance(n);
}
}
if (cheie < n->cheie)
n->st = Sterge(n->st, cheie);
else
n->dr = Sterge(n->dr, cheie);
return Balance(n);
}
void AVL::StergeArbore(Node *n)
{
if(n == NIL)
return;
StergeArbore(n->dr);
StergeArbore(n->st);
delete n;
}
bool AVL::Cauta(Node *n, int cheie)
{
if (n == NIL)
return false;
if (n->cheie == cheie)
return true;
if (cheie < n->cheie)
return Cauta(n->st, cheie);
else
return Cauta(n->dr, cheie);
}
void AVL::Nivele()
{
// verificari
if(rad == NULL)
{
cout<<"Arborele e gol!\n";
return;
}
// variabile auxiliare
Node ** coada = new Node*[nrNoduri]; // retine nodurile parcurse in latime
int *nivele = new int[nrNoduri]; // retine nivelul pe care se afla fiecare nod
Node *x;
int inc, sf; // inceputul si sfarsitul cozii
// initializam nivelele, coada.
nivele[0] = 1; // nivelul nodurilor
coada[0] = rad; // primul nod din coada
inc = sf = 0; // inceputul si sfasitul cozii
// cata vreme avem noduri in coada
cout<<"\nNivel 1: ";
while(inc <= sf)
{
// afisam primul nod din coada
x = coada[inc];
cout<<x->cheie<<" ";
// bagam fii ultimului nod in coada
// si completam nivelul nodurilor
if(x->st != NIL)
{
coada[++sf] = x->st;
nivele[sf] = nivele[inc]+1;
}
if(x->dr != NIL)
{
coada[++sf] = x->dr;
nivele[sf] = nivele[inc]+1;
}
// scoatem primul nod din coada
inc++;
// afisam nivelul daca este diferit de nivelul nodului precedent
if(nivele[inc] != nivele[inc-1] && inc <= sf)
cout<<"\nNivel "<<nivele[inc]<<": ";
}
// stergem memoria folosita pentru retinerea cozii si a nivelului nodului
delete[] coada;
delete[] nivele;
}