Documente Academic
Documente Profesional
Documente Cultură
Arbori Anderson-Velski-Landis
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.
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
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