Sunteți pe pagina 1din 12

ACADEMIA DE STUDII ECONOMICE

FACULTATEA DE CIBERNETIC, STATISTIC i INFORMATIC ECONOMIC

STRUCTURI DE DATE PROIECT

Arbori Anderson-Velski-Landis

Student : Delcea Sorin-Paul Grupa : 1056 An: III

Bucureti 2009

Cuprins
Introducere.............................................................................................. 3 Structura Programului........................................................................... 4 Structurile de date utilizate.................................................................... 5 Descrierea implementarii operatiilor de baza...................................... 6 Concluzii.................................................................................................. 8 Bibliografie.............................................................................................. 9 Anexe....................................................................................................... 10

Introducere
Obiectivul lucrarii este de a gestiona cat mai bine un depozit al unei societati comerciale in care sunt depozitate mai multe produse de acelasi tip. Deoarece depozitul poate avea foarte multe produse in evidenta, este de dorit ca eventualele operatii care se vor face (adaugare de produs respectiv stergere de produs din evidenta) sa se faca foarte rapid. De aceea s-a optat pentru implementarea unei structuri de date arborescenta, si anume arbore AVL. Acest tip de arbori permit efectuarea de operatii specifice foarte rapid si deci sunt ideali pentru rezolvarea problemei. Proiectul implementeaza logica de arbore AVL a carui structura va fi prezentata la punctul 5 al acestei lucrari, precum si numeroase proceduri ce servesc la o utilizare cat mai eficienta a programului.

Structura programului
Programul este permite utilizatorului sa aleaga o optiune, in functie de ceea ce doreste sa faca: sa adauge un nou produs in stoc, sa stearga informatia despre un produs din stoc sau sa afiseze toate produsele care sunt prezente in stoc la momentul respectiv. Programul a fost realizat in asa fel incat, toate produsele sa fie stocate dupa codul produsului intr-un arbore binar de cautare echilibrat datorita timpilor foarte buni de cautare pe care ii are aceasta structura. Dupa fiecare operatie la care este supus arborele se apeleaza la o procedura de reechilibrare, daca este cazul, echilibrare care se face utilizand algoritmul arborilor AVL. Pentru usurinta si pentru a nu se complica programul, utilizatorul trebuie sa introduca numai codul produsului, acesta reprezentant informatia utila a nodulurilor din arbore. Algoritmul functioneaza dupa urmatorul principiu: Daca s-a adaugat sau s-a sters o informatie din arbore, se calculeaza pentru fiecare nod factorul de echilibru al acestuia. In functie de acest factor se aplica una din cele patru proceduri de echilibrare a arborilor Anderson-Velski-Landis (rotatie la stanga, rotatie la dreapta, rotatie stanga-dreapta respectiv dreapta-stanga). La unul din punctele urmatoare vor fi prezentate toate procedurile care alcatuiesc programul.

Structurile de date utilizate intern


Principala structura de date utilizata este arborele AVL. Arborii AVL sunt arbori binari de cautare care sunt echilibrati si poarta numele celor care i-au inventat Anderson Velski Landis. Cea mai importanta proprietate a acestor arbori este aceea ca acestia raman echilibrati si dupa ce s-au efectuat operatii asupra lor, pentru aceasta utilizandu-se un set de algoritmi de echilibrare in functie de factorul de dezechilibru (2, -2). Spunem despre un arbore AVL ca este echilibrat daca are un factor de dezechilibru in multimea {-1, 0, 1} adica diferenta dintre nivelul subarborelui drept si cea a subarborelui drept a unui nod al arborelui nu este mai mare decat 1, in modul. Daca in urma unei operaii arborele a fost dezechilibrat si un nod are factorul de echilibru -2 spunem ca arborele este dezechilibrat si necesita pentru echilibrare aplicarea rotatiei la dreapta. In celalalt caz se aplica similar metoda rotatiei la stanga in vederea echilibrarii. Exista si cazurile in care un arbore are un nod care este dezechilibrat de factor -2 dar are un subarbre dezechilibrat de factor 1, caz in care se aplica o echilibrare formata din doi pasi, metoda numita rotatie dreapta-stanga. Pentru cazul opus este folosita echilibrarea prin metoda rotatiei stanga-dreapta. In cadrul programului au fost implementate toate aceste proceduri precum si operatii elementare specifice arborilor cum ar fi parcurgerea arborilor in vederea cautarii unui nod in functie de informatia utila continuta, stergerea unui nod din arbore, inserarea de nod in arbore.

Descrierea implementarii operatiilor de baza


In vederea realizarii scopului propus, acela de a implementa arborele AVL pe problema noastra, a fost nevoie de folosirea mai multor proceduri care vor fi descrise in cele ce urmeaza. In primul rand a fost implementata procedura de calcul a drumului cel mai lung de la un nod la o frunza a sa, procedura necesara ulterior in calculul factorului de echilibru. Procedura este CMLdrum si primeste ca parametrii un pointer la un nod al arborelui si doau variabile de tip intreg pentru calculul lungimii drumului max, respectiv lung void CMLdrum(arboreBinAVL* rad,int &max,int lung){
if (rad!=NULL){ CMLdrum(rad->sd,max,lung+1); if ((rad->ss==NULL)&&(rad->sd==NULL)&&(max<lung)) max=lung; CMLdrum(rad->ss,max,lung+1); } }

O alta procedura importanta in economia programului este procedura pentru calculul factorlui de echilibru: factor_echil. Aceasta procedura primeste ca argument un pointer catre o structura de tipul nodului arborelui si calculeaza factorul de echilbru facand diferenta dintre cel mai lung drum din al subarborelui drapt si cel al subarborelui stang.
void factor_echil(arboreBinAVL *rad){ int max1,max2; max1=1; max2=1; if(rad->ss != NULL) CMLdrum(rad->ss,max1,1); else max1=0; if(rad->sd != NULL) CMLdrum(rad->sd,max2,1); else max2=0; rad->ech=max2-max1;

Procedurile de echilibrare a arborelui au fost construite folosind logica rotatiilor, in functie de factorul de echilibrare. In continuare va fi prezentata doar una din ele, celelalte fiind asemanatoare. Spre exemplificare am ales rotatia la dreapta pentru care vom prezenta algoritmul: - Se parcurge arborele si se alege drept pivot primul nod cu factorul de echilibru -2, incepand de sus in jos. - Se deconecteaza subarborele drept al fiului stang al nodului pivot. - Se executa rotatia la dreapta si nodul stang al pivotului devine radacina, toate celelalte noduri glisandu-se catre dreapta, ca un scripete. - Se conecteaza subarborele deconectat ca subarbore stang al nodului pivot. - Se recalculeaza factorul de echilibru si se repeta operatia pana cand arborele este echilibrat
arboreBinAVL* rot_drt(arboreBinAVL *rad){

arboreBinAVL* aux; aux=rad->sd; rad->sd=aux->ss; aux->ss=rad; factor_echil(rad); factor_echil(aux); rad=aux; return rad; } arboreBinAVL* rot_stg(arboreBinAVL *rad){ arboreBinAVL* aux; aux=rad->ss; rad->ss=aux->sd; aux->sd=rad; factor_echil(rad); factor_echil(aux); rad=aux; return rad; } arboreBinAVL* rot_drt_stg(arboreBinAVL *rad){ rad->sd = rot_stg(rad->sd); rad = rot_drt(rad); return rad; } arboreBinAVL* rot_stg_drt(arboreBinAVL *rad){ rad->ss = rot_drt(rad->ss); rad = rot_stg(rad); return rad; } arboreBinAVL* echilibrare(arboreBinAVL *rad){ arboreBinAVL *w; factor_echil(rad); if(rad->ech==-2){ w=rad->ss; if (w->ech==1) rad = rot_stg_drt(rad); else rad = rot_stg_drt(rad); } else if(rad->ech==2){ w=rad->sd; if (w->ech==-1) rad = rot_drt_stg(rad); else rad = rot_drt(rad); } return rad; }

Programul contine, evident si proceduri specifice lucrului cu arbori binari precum crearea de nod, inserarea de nod si extragerea de nod din arbore, precum si o procedura de afisare a arborelui pe nivele. 7

Pentru restul codului si functia main se poate verifica sectiunea de Anexe.

Concluzii
S-a demonstrat ca arborii AVL au un NC <= 1.44 log2 (n + 2) si ca urmare a acestui lucru au timpi de cautare foarte buni si sunt ideali pentru lucrul cu baze de date de dimensiuni mari si foarte mari si este eficient si pentru problema noastra. In urma testelor care s-au efectuat, s-a putut observa ca toate procedurile sunt corecte si ca arborele AVL utilizat pentru rezolvarea problemei este solutia optima, desi nu este un arbore echilibrat perfect.

Bibliografie
[SMEU2002] - Ion SMEUREANU, Marian DARDAL Programarea orientata obiect in limbajul C++, Editura Cison, 2002 [SMEU2004] - Ion SMEUREANU, Marian DARDAL Programarea in limbajul C/C++, Editura Cison, 2004. Seminar 13 Structuri de Date, profesor Cristian Toma, ASE, CSIE, grupa 1056, 6 Ian 2009.

Anexa
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include<malloc.h> struct arboreBinAVL{ int codp; int ech; arboreBinAVL* ss, *sd; }; arboreBinAVL *r; void CMLdrum(arboreBinAVL* rad,int &max,int lung){ if (rad!=NULL){ CMLdrum(rad->sd,max,lung+1); if ((rad->ss==NULL)&&(rad->sd==NULL)&&(max<lung)) max=lung; CMLdrum(rad->ss,max,lung+1); } } void factor_echil(arboreBinAVL *rad){ int max1,max2; max1=1; max2=1; if(rad->ss != NULL) CMLdrum(rad->ss,max1,1); else max1=0; if(rad->sd != NULL) CMLdrum(rad->sd,max2,1); else max2=0; rad->ech=max2-max1; } arboreBinAVL* rot_drt(arboreBinAVL *rad){ arboreBinAVL* aux; aux=rad->sd; rad->sd=aux->ss; aux->ss=rad; factor_echil(rad); factor_echil(aux); rad=aux; return rad; } arboreBinAVL* rot_stg(arboreBinAVL *rad){ arboreBinAVL* aux; aux=rad->ss; rad->ss=aux->sd; aux->sd=rad; factor_echil(rad); factor_echil(aux);

rad=aux; return rad; } arboreBinAVL* rot_drt_stg(arboreBinAVL *rad){ rad->sd = rot_stg(rad->sd); rad = rot_drt(rad); return rad; } arboreBinAVL* rot_stg_drt(arboreBinAVL *rad){ rad->ss = rot_drt(rad->ss); rad = rot_stg(rad); return rad; } arboreBinAVL* echilibrare(arboreBinAVL *rad){ arboreBinAVL *w; factor_echil(rad); if(rad->ech==-2){ w=rad->ss; if (w->ech==1) rad = rot_stg_drt(rad); else rad = rot_stg_drt(rad); } else if(rad->ech==2){ w=rad->sd; if (w->ech==-1) rad = rot_drt_stg(rad); else rad = rot_drt(rad); } return rad; } arboreBinAVL *insereaza(arboreBinAVL *rad,int x){ if(rad==NULL){ if (x!=0){ rad=(arboreBinAVL*)malloc(sizeof(arboreBinAVL)); rad->codp=x; rad->ech=0; rad->sd=NULL; rad->ss=NULL; return rad; } } else if (x<rad->codp) rad->ss=insereaza(rad->ss,x); else if (x>rad->codp) rad->sd=insereaza(rad->sd,x); else printf("Nodul exista deja");

10

rad = echilibrare(rad); } arboreBinAVL *stergere(arboreBinAVL *rad,int x){ arboreBinAVL *q,*r,*w; if (rad!=NULL) if (x<rad->codp) rad->ss = stergere(rad->ss,x); else if (x>rad->codp) rad->sd = stergere(rad->sd,x); else{ q=rad; if (q->sd==NULL) rad=q->ss; else if (q->ss==NULL) rad=q->sd; else{ w=q->ss; r=q; if (w->sd!=NULL) { while (w->sd!=NULL){ r=w; w=w->sd; } rad->codp=w->codp; q=w; r->sd=w->ss; r=rad->ss; w=w->ss; if (r!=NULL) while ((r!=w)&&(r!=NULL)){ r = echilibrare(r); r=r->sd; } } else{ rad->codp=w->codp; rad->ss=w->ss; q=w; } } free(q);// } if (rad!=NULL) rad = echilibrare(rad); return rad; } void afisare_nivel(arboreBinAVL *rad ,int l){ int i; if (rad!=NULL){ afisare_nivel(rad->sd,l+5);

11

for ( i=0;i<l;i++) printf(" "); printf("%d",rad->codp ); for ( i=0;i<l;i++) printf(" "); printf("\n"); afisare_nivel(rad->ss,l+5); } } void creare(){ int x; printf("\n codp=");scanf("%d",&x); while (x!=0){ r=insereaza(r,x); printf("\n codp=");scanf("%d",&x); } } void stergere(){ int x; printf("\n dati cheia ");scanf("%d",&x); r=stergere(r,x); } int main(){ char ch; r=NULL; do{ printf("\n. . .> 1 <. .INSERAREA IN ARBORE AVL"); printf("\n. . .> 2 <. .AFISAREA ARBORELUI AVL"); printf("\n. . .> 3 <. .STERGEREA IN ARBORELE AVL"); printf("\n\n. . .> x <. .EXIT\n\n"); ch=getchar(); switch(ch){ case '1':creare();break; case '2':afisare_nivel(r,1);break; case '3':stergere();break; } }while (ch!='x'); getchar(); return 1; }

12