Laborator de Structuri de Date si Algoritmi – Lucrarea nr.

5

Arbori de grad oarecare. Arbori binari
I. Arbori de grad oarecare I.1. Reprezentarea standard I.2. Reprezentarea FIU-FRATE I.3. Reprezentarea prin noduri de dimensiune variabila II. Arbori binari II.1. Reprezentarea standard II.2. Parcurgeri II.3. Exemplu: calcularea valorii maxime dintr-un arbore binar

I. Arbori de grad oarecare
I.1. Reprezentarea "standard"
In reprezentarea standard in fiecare nod al arborelui, pe linga informatia utila se memoreaza informatii de inlantuire care indica descendentii. Intr-o prima varianta de reprezentare, fiecare nod este compus din informatia utila si un vector de dimensine fixa, in care se memoreaza legaturilor de tip pointer la descendenti. Dimensiunea acestui vector este data gradul maxim al nodurilor arborelui. Declaratiile de tip folosite de aceasta reprezentare sint: struct Nod{ Atom data; Nod* vDesc[GRMAX]; }; Un nod va ocupa o zona de memorie de dimensiune fixa:

In figura de mai jos am reprezentat inlantuirile pentru arborele:

In consecinta aceasta reprezentare este acceptabila numai pentru arbori de grad mic. deci in total N-1 elemente din vectorii de pointeri la descendenti sint ocupate cu informatie utila. Nod* next. doi pointeri: unul va indica lista cu descendentii sai iar cel de-al doilea urmatorul nod din lista de descendenti din care face parte. Nod* desc.Laborator de Structuri de Date si Algoritmi – Lucrarea nr. struct Nod { Atom data. descendentul i al nodului va fi identificat direct prin pointerul p->vDesc[i] Intr-un arbore cu un numar N de noduri vor exista N-1 muchii. pot fi utilizate listele de descendenti. Fiecare nod va contine pe linga informatia utila. }. 5 In aceasta reprezentare. Reprezentarea "FIU-FRATE" Pentru a obtine o utilizare mai eficienta a memoriei. .2. I. daca p este un pointer la un nod. Se obtine raportul: N −1 1 = N * GRMAX GRMAX care indica gradul de utilizare eficienta a memoriei.

}. adugind in plus un cimp in care sa se memoreze gradul nodului. daca p este un pointer la un nod. Iata cum vor arata: . Vom considera aceeasi declaratie pentru tipul Nod ca si in prima varinata de reprezentare. Aceasta solutie se bazeaza pe posibilitatea de a aloca blocuri de memorie de lungime precizata.3. adaptata gradului fiecarui nod. In aceasta reprezentare. lista care incepe cu: p->desc I. struct Nod{ Atom data. int grad. 5 In aceasta varianta arborele de mai sus va avea urmatoarea reprezentare: Avind in vedere semnificatia pointerilor continuti intr-un nod aceasta reprezentare se mai numeste "reprezentarea FIU-FRATE". identificarea descendentul i al nodului va necesita parcurgerea listei inlantuite a descendentilor.Un nod de grad 3: . Reprezentarea prin noduri de dimensiune variabila O a treia solutie de reprezentare combina economia de memorie cu avantajele accesarii descendentilor pe baza de index. Nod* vDesc[GRMAX].Laborator de Structuri de Date si Algoritmi – Lucrarea nr. Economia de memorie se va realiza prin alocarea unor zone de memorie de lungime variabila.

reprezentarea arborelui dat: TEMA 1 Functia Nod* creareArbore(). return p.Un nod terminal: Pentru a realiza economia de memorie este necesar ca la alocarea spatiului pentru un nod sa se cunoasca numarul de descendenti si in functie de acest numar sa se aloce spatiul necesar pentru vectorul de descendenti. alocarea va avea forma: Nod* p = (Nod*) new char[sizeof(Nod)-(GRMAX-grad)*sizeof(Nod*)].Un nod de grad 1: . Iata cum trebuie scrisa functia make_nod care aloca spatiu pentru un nod de grad dat: Nod* make_nod(int grad) { Nod *p=(Nod*)malloc(sizeof(Nod)-(GRMAX-grad)*sizeof(Nod*)).Laborator de Structuri de Date si Algoritmi – Lucrarea nr. Iata cum va arata. . p->grad = grad. specific limbajului C++. } Utilizind operatorul new. 5 . in aceasta varianta.

II. *drt. 5 din AnexaA citeste de la intrare o expresie aritmetica. care contine operanzi de o cifra si operatorii + si *. ■ Sa se afiseze valoarea tuturor operanzilor utilizati in expresie (fara operatori). si creaza arborele de grad oarecare asociat expresiei. Arbori binari 1. }. Nod* stg. cu paranteze. un nod al arborelui este o structura cu un cimp continind eticheta nodului (data) si doua cimpuri pointeri la cei doi descendenti (lchild si rchild): struct Nod { type data. tipul Atom fiind echivalat cu tipul int (vezi Anexa A). Astfel. Reprezentarea standard In reprezentarea standard.Laborator de Structuri de Date si Algoritmi – Lucrarea nr. ■ Sa se evalueze expresia si sa se afiseze rezultatul. Se cere: ■ Sa se determine si sa se afiseze gradul arborelui. De exemplu: 1+2*3+4*(5+6) i se asociaza arborele: Arborele este reprezentat dupa metoda 3. arborele: va avea urmatoarea reprezentare: .

Laborator de Structuri de Date si Algoritmi – Lucrarea nr. Pacurgeri Un arbore binar poate fi privit conform urmatoarei scheme recursive: rad = radacina SAS = SubArbore Sting SAD = SubArbore Drept Pe aceasta schema se definesc cele trei moduri de parcurgere a arborelui: PREORDINE : rad SAS SAD Se prelucreaza mai intii radacina apoi se parcurg in preordine subarborii sting si drept. se prelucreaza radacina si apoi se parcurge in inordine subarborele drept. INORDINE : SAS rad SAD Se parcurge in inordone subarborele sting.2. POSTORDINE : SAS SAD rad Se parcurg mai intii in postordine subarborii sting si drept apoi se prelucreaza radacina. Valoarea nil pentru acest pointer va semnifica un arbore vid. II. Pentru arborele: . 5 Pentru a putea prelucra un arbore este suficient sa cunostem un pointer la nodul radacina.

{ if (p!=NULL){ ┌───────────────────┐ │ prelucreaza(*p). in schimb executa un apel recursiv in plus pentru fiecare legatura care este NULL. { ┌──────────────────┐ │ prelucreaza(*p). } } sau void PREORDINE(Nod* p). 5 cele trei parcurgeri prelucreaza nodurile in ordinea: PREORDINE: INORDINE: POSTORDINE: ABDCEF BDAECF DBEFCA Putem realiza aceste parcurgeri utilizind subrutine recursive. // max este variabila globala void CautaMax(Nod* p) {/* ----------------Parcurgere preordine Varianta 2*/ if (p!=NULL){ if (p->data>max) max=p->data. │ └──────────────────┘ if(p->stg!=NULL) PREORDINE(p->stg). Exemplu . │ └───────────────────┘ PREORDINE(p->lchild).Calcularea valoarii maxime dintr-un arbore binar Varianta 1 char max .3. PREORDINE(p->rchild). } A doua varianta nu poate fi aplicata unui arbore vid.Laborator de Structuri de Date si Algoritmi – Lucrarea nr. II. in timp ce prima trateaza corect arborele vid. . if(p->drt!=NULL) PREORDINE(p->drt). De exemplu: void PREORDINE(pNod p).

} char ValMax(pNod rad) { char vmax.char v2) { if(v1>=v2) return v1. La sfirsitul parcurgerii. ValMax(SAD)) Apelurile ValMax(SAS) si ValMax(SAD) se vor executa numai daca subarborii nu sint vizi. care este o variabila globala (externa) pentru procedura recursiva. return max. va contine valoarea maxima a etichetelor din arbore. Iata implementarea: char max(char v1. else return v2. } Functia Valmax apeleaza o procedura recursiva CautaMax care face o parcurgere prin arbore testind valoarea fiecarui nod. si care a fost initializata cu cea mai mica valoare de tip char. } } char ValMax(Nod* p) { max = 0. . ValMax(SAS). variabila "max".Laborator de Structuri de Date si Algoritmi – Lucrarea nr. CautaMax(p->drt). CautaMax(rad). Varianta 2 Pornind de la schema: stabilim urmatoarea definitie recursiva: ValMax(arbore) = max(rad. 5 CautaMax(p->stg).

CPP (vezi ANEXA B) contine declaratiile tipurilor: struct Nod { char data. si intoarce pointer la radacina arborelui citit.ValMax(rad->lchild)). *drt. In diagrama: '-' -semnifica un arbore vid. care citeste un arbore specificat conform urmatoarei diagrame de sintaxa. Modulul ARBORE_BINAR. return vmax. if rad->lchild!=NULL vmax = max(vmax. struct Nod *stg. } Aceasta varianta nu se poate aplica unui arbore vid. 5 vmax = rad->data. Exemple: Arborele vid: - .ValMax(rad->rchild)). nume -este eticheta unui nod formata dintr-o litera. } si functia: Nod* creareArboreB(). TEMA 2 1. valoarea 0). if rad->rchild!=NULL vmax = max(vmax. dar are avantajul ca se poate aplica si in cazuri in care nu exista o valoare de eticheta pentru nod mai mica decit toate etichetele posibile (cum am folosit mai sus.Laborator de Structuri de Date si Algoritmi – Lucrarea nr.

cele doua variante de abordare prezentate in exemplul cu aflarea valorii maxime): Sa se afiseze continutul arborelui in INORDINE. Sa se afiseze continutul arborelui in POSTORDINE. O functie pentru determinarea adincimii arborelui. Incercati pe rind. Creeaza arborele expresiei si calculeaza valoarea expresiei pe arbore. numere intregi de o cifra. De exemplu expresia: (1+3)*4*(5+6) este citita in arborele: . O functie pentru determinarea numarului de frunze ale arborelui. 5 Sa se scrie si sa se testeze urmatoarele subrutine. si operatorii + si *. Sa se scrie un program care citeste expresii formate din operanzi.Laborator de Structuri de Date si Algoritmi – Lucrarea nr. pentru fiecare. 2. O functie pentru determinarea numarului de noduri din arbore. Pentru fiecare nod sa se comute subarborele sting cu cel drept si sa se afiseze continutul arborelui in forma cu paranteze. Sa se afiseze toate nodurile care au valoarea din radacina mai mare decit toate valorile din subarborii descendenti. Sa se afiseze toate nodurile pentru care toate valorile continute in subarborele sting sint mai mici decit toate valorile continute in subarborele drept.

h> <iostream. int length = strlen(buffer).h" <string.h> <stdio. int grad. return n.cpp #include #include #include #include #include #include #include "arbore. Nod* n = parse(buffer.Laborator de Structuri de Date si Algoritmi – Lucrarea nr. Nod* creareArbore() { char buffer[DIM_EXPR].h> Nod* parse(char buffer[]. #endif Fisierul Arbore.h> <conio. int start. Nod* vDesc[GRMAX].h #ifndef _ARBORE_H_ #define _ARBORE_H_ #define DIM_EXPR 100 #define GRMAX #define Atom 20 int struct Nod { Atom data. length-1).h> <ctype. Nod* creareArbore(). }. cin >> buffer.h> <stdlib. 0. 5 Anexa A Fisierul Arbore. } . int end).

j < p->grad . for (i = start. return p.Laborator de Structuri de Date si Algoritmi – Lucrarea nr. if ( buffer[i]==')' ) openP --. indici[GRMAX]. } openP = 0. indici[k++] = i. i <= end. indici[0]-1). i++) { if ( buffer[i]=='(' ) openP ++. . j++) { p->vDesc[j] = parse(buffer. i <= end. } p->vDesc[p->grad-1] = parse(buffer. p->vDesc[0] = parse(buffer. openP = 0. i++) { if ( buffer[i]=='(' ) openP ++. 5 Nod* { int int int parse(char buffer[]. p->data='+'. indici[k++] = i. indici[p->grad-2]+1. for (int i = start. p->grad = k+1. if ( buffer[i]==')' ) openP --. if ( buffer[i]=='*' ) { if ( openP > 0) continue. p->grad = k+1. } } if ( k > 0 ) { Nod *p=(Nod*) new char[sizeof(Nod)-(GRMAX-k+1)*sizeof(Nod*)]. indici[j-1]+1. start. end). int end) openP = 0. int start. } } if ( k > 0 ) { Nod *p=(Nod*) new char[sizeof(Nod)-(GRMAX-k+1)*sizeof(Nod*)]. k = 0. indici[j]-1). for (int j = 1.1. if ( buffer[i]=='+' ) { if ( openP > 0) continue.

p->vDesc[0] = parse(buffer. 5 p->data='*'. exit(1). indici[j]-1). indici[0]-1). return p. p->data = buffer[start]. if ( start==end ) if ( isdigit(buffer[start]) ) { Nod* p = (Nod*) new char[sizeof(Nod)-(GRMAX)*sizeof(Nod*)]. end). getch(). indici[p->grad-2]+1. j++) { p->vDesc[j] = parse(buffer. p->grad = 0. j < p->grad .Laborator de Structuri de Date si Algoritmi – Lucrarea nr. indici[j-1]+1. end-1). } . for (int j = 1.1. start. } if ( buffer[start] == '(' && buffer[end] == ')' ) return parse(buffer. start+1. } p->vDesc[p->grad-1] = parse(buffer. } printf("\nExpresia de intrare este eronata. return p. Apasati o tasta").

citesteNume(). if(!isalpha(car)) eroare().h> <conio. }. Nod* stg. char citesteNume() { char c. exit(1).. citesteArboreB().cpp #include #include #include #include #include #include char car. .h" while(c==' '). } char readchar() { char c. Arbore_binar.h> <stdio. } <alloc. *drt. 5 ANEXA B Arbore_binar.. printf("Apasati tasta o tasta. do c=getchar().h struct Nod{ char data. readchar(). void char char Nod* Nod* eroare(). void eroare() { printf("Sirul de intrare este eronat!\n").").h> "arbore_binar. return c. getch().h> <ctype.Laborator de Structuri de Date si Algoritmi – Lucrarea nr.h> <stdlib. c = car. creareArboreB().

rad->data = citesteNume(). rad->stg = citesteArboreB(). rad->drt = citesteArboreB(). return c.Laborator de Structuri de Date si Algoritmi – Lucrarea nr.' ) rad->drt = 0. } Nod* citesteArboreB() { Nod* rad. car = readchar(). return citesteArboreB(). if( car!='(' ) { rad->stg = 0. } . 5 car = readchar(). else { car = readchar(). car = readchar(). if( car!='. } Nod* creareArboreB() { printf("\nIntroduceti arborele:"). car = readchar(). } else { rad = (Nod*) malloc(sizeof(Nod)). if( car=='-' ) { rad=0. } else { car = readchar(). } } return rad. rad->drt = 0. } if( car!=')' ) eroare().

Sign up to vote on this title
UsefulNot useful