Sunteți pe pagina 1din 13

Tema: „Analiza prelucrării programelor cu arbori.

Sarcina și obiectivele:
1. De studiat și însușit materialul teoretic pentru evidențierea esențialului prelucrării
arborilor în elaborarea modelelor soluției, analizînd exemplele din indicații metodice.
2. Să se analizeze tehnica modelării și programării eficiente pentru diverse
compartimente ale diferitor situații cu diverse argumentări și modele de arbori.

Întrebări de autocontrol:
1. Ce este un arbore?
Un arbore reprezintă un graf particular, în care substructurile legate la orice nod sunt
disjunctive și în care există un nod numit rădăcină din care e accesibil orice nod prin
traversarea unui număr finit de arce. În teoria grafurilor, un arbore este un graf
neorientat, conex și fără cicluri. Arborii reprezintă grafurile cele mai simple ca
structură din clasa grafurilor conexe.
2. Ce este un arbore binar?
Un arbore binar e un arbore orientat, în care fiecare vârf are maximum 2 descendenți.
Un arbore binar în care orice vârf are 1 sau 2 descendenți se numește arbore binar
complet.
3. Ce este un arbore binar echilibrat?
Arborele binar echilibrat e acel pentru fiecare a cărui număr de noduri din subarborele
stâng diferă de cel din subarborele drept cu cel mult 1.
4. Care sunt metodele principale de parcurgere a unui arbore?
Există 3 metode principale de parcurgere a unui arbore și anume:
a. preordine – mai întâi se prelucrează informația din nod și apoi se parcurge prin
arbore.
b. inordine – mai întâi se parcurge subarborele stâng, apoi se vizitează rădăcina și
apoi subarborele drept.
c. postordine – mai întâi se parcurgere subarborele stâng, subarborele drept și apoi
vizităm rădăcina.
5. Care este numărul maxim de noduri dintr-un arbore binar de înălțimea 5?
Folosind formula 2K+1-1 obținem că într-un arbore de înălțimea 5 putem avea maxim
63 de noduri.
a) 15
b) 31
c) 63
d) 64
6. Care este numărul minim de noduri dintr-un arbore AVL de înălțimea 5?
Folosind formula N(h) = 1 + N(h-1) + N(h-2). Știind că N(0) = 0, N(1) = 2 și N(2) = 4
atunci avem:
N(3)=1+N(3-1)+N(3-2)=1+N(2)+N(1)=7
N(4)=1+N(4-1)+N(4-2)=1+N(3)+N(2)=12
N(5)=1+N(5-1)+N(5-2)=1+N(4)+N(3)=20
Numărul minim de noduri va fi = 20.
7. Parcurgând în inordine un arbore binar, în ce ordine vor fi ordonate cheile?
a)descrescatoare
b)crescatoare
c)in nici o ordine
d)la inceput crescatoare, apoi descrescatoare
8. Se consideră arborele binar de căutare din figură:
7
/\
3 10
/\/\
2 5 8 13

dacă se parcurge în inordine acest arbore, ordinea corectă a vizitării nodurilor este:
c) 2,3,5,8,10,13.
9. Într-un arbore AVL vid, se înserează următoarele chei: 1, 2, 3, 4, 5 ,6 (în această
ordine). Care este configurația arborelui după înserarea ultimei chei?
4
/\
2 5
/ \ \
1 3 6
10.Dacă un arbore binar de căutare după înălțime conține 635 noduri, pentru
regăsirea unei înregistrări, câte comparații necesită în ce mai bun caz?
Folosind expresia Log2(635) = 9,31 atunci obținem că în cel mai bun caz algoritmul
necesită 9 comparații.
11.Se consideră următorul arbore binar de căutare:
7
/\
3 12
/ \
1 5 14
Cheia predecesoare pentru 3 este ?
12.Se consideră următorul arbore binar de căutare:
7
/\
5 10
/\
2 20
\
4
/
3
În urma ștergerii nodului cu cheia 7, arborele va arăta astfel:
10
/\
5 20
/
2
\
4
/
3

13. Care afirmație este adevărată?


a)Arborii B sunt intotdeauna perfect echilibrati.
b)Arborii AVL sunt intotdeauna perfect echilibrati.
c)Arborii B nu sunt intotdeauna perfect echilibrati.
d)Arborii AVL si B sunt intotdeauna perfect echilibrati.
14.Se consideră următorul arbore binar de căutare:
7
/\
69
/ /
3 8
În urma înserării cheilor 12, 4, 10 în această ordine, arborele va arăta în felul următor:
7
/\
69
//\
3 8 10
\\
4 12
15.Într-un arbore AVL, un nod devine critic atunci când:
a)factorul sau de echilibrare devine 2;
b)factorul sau de echilibrare devine -2;
c)factorul sau de echilibrare devine 2 sau -2;
d)factorul sau de echilibrare devine 1 sau -1;
16.În urma înserării unui nod într-un arbore AVL, acesta se poate dezechilibra. În
cazul în care se dezechilibrează care dintre următoarele operațiuni se pot folosi
pentru reechilibrare?
a)se insereaza noduri, pana cand devine echilibrat;
b)se sterg noduri, pana cand devine echilibrat;
c)se efectueaza rotatii pentru nodurile critice;
d)nu se poate face nimic;
17.Un nod dintr-un arbore binar de căutare are:
a)exact doi copii;
b)nu mai mult de doi copii;
c)doi sau mai multi copii;
d)oricati copii, depinzand de gradul sau;
18.Pentru un arbore binar de căutare de înălțime 5, care este numărul maxim de
frunze la care acesta poate să ajungă?
a)15
b)16
c)18
d)22
Sarcinile propuse spre analiză și rezolvare:
Sarcina 1. Să se analizeze succint domeniul și obiectivul programului din exemplul 16
din indicații metodice. Să se construiască organigramele principale.
 Organigrame:

Organigrama arborelui inițial.

Ștergerea unui nod al arborelui.

Organigrama arborelui după ștergerea elementului G.


 Listingul programului:
1. //  
2. // Created by Victor Rusu on 4/29/17.  
3. //  
4.   
5. #include <stdio.h>  
6. #include <stdlib.h>  
7. #include <time.h>  
8.   
9. struct node{  
10.     char key;  
11.     struct node *left, *right;  
12. };  
13. struct node *newNode(char item);  
14. struct node *insert(struct node* node, char key);  
15. struct node *printTreeTriangle(struct node *tree, int level);  
16. struct node *minValueNode(struct node* node);  
17. struct node *deleteNode(struct node* root, char key);  
18.   
19. int main(){  
20.     clock_t start, stop;  
21.     start = clock();  
22.     struct node *root = NULL;  
23.     root = insert(root, 'E');  
24.     root = insert(root, 'C');  
25.     root = insert(root, 'B');  
26.     root = insert(root, 'D');  
27.     root = insert(root, 'G');  
28.     root = insert(root, 'F');  
29.     root = insert(root, 'H');  
30.   
31.     printTreeTriangle(root,0);  
32.     root = deleteNode(root, 'G');  
33.     printf("\n\n\n");  
34.     printTreeTriangle(root,0);  
35.     stop = clock();  
36.     printf("\nProgramul sa executat în %f secunde.",(double) (stop-
start)/CLOCKS_PER_SEC);  
37.     return 0;  
38. }  
39.   
40. /* 
41.  * Funcție ce afișează datele sub formă 
42.  *      de arbore. 
43.  */  
44. struct node *printTreeTriangle(struct node *tree, int level) {  
45.     int i;  
46.     if(tree) {  
47.         printTreeTriangle(tree->right,level+1);  
48.         printf("\n\n");  
49.         for (i=0;i<level;i++){  
50.             printf("       ");  
51.         }  
52.         printf("%c",tree->key);  
53.         printTreeTriangle(tree->left,level+1);  
54.     }  
55.     return(NULL);  
56. }  
57.   
58. /* 
59.  * Funcție ce crează un nod nou. 
60.  * 
61.  * char item -> parametru ce specifică 
62.  *     valoarea pe care o va lua nodul 
63.  *     nou creat. 
64.  */  
65. struct node *newNode(char item){  
66.     struct node *temp = (struct node *) malloc(sizeof(struct node));  
67.     temp->key = item;  
68.     temp->left = temp->right = NULL;  
69.     return temp;  
70. }  
71.   
72. /* 
73.  * Funcție ce adaugă un element în arbore. 
74.  * 
75.  * struct node* node -> specifică arborele 
76.  *      în care va fi adăugat nodul. 
77.  * char key -> valoarea pe care o va lua 
78.  *      nodul nou introdus. 
79.  */  
80. struct node* insert(struct node* node, char key) {  
81.     /* dacă arborele este gol, returnăm un nod nou */  
82.     if (node == NULL) return newNode(key);  
83.     /* în caz contrat */  
84.     if ((int)key < (int)node->key) {  
85.         node->left = insert(node->left, key);  
86.     } else{  
87.         node->right = insert(node->right, key);  
88.     }  
89.     return node;  
90. }  
91.   
92. /* 
93.  * Funcție ce șterge un element. 
94.  * 
95.  * struct node* root -> specifică structura din 
96.  *      care va fi șters nodul. 
97.  * char key -> specifică valoarea nodului 
98.  *      ce va fi șters. 
99.  */  
100. struct node* deleteNode(struct node* root, char key) {  
101.     // caz genera;  
102.     if (root == NULL)  {  
103.         return root;  
104.     }  
105.     //Dacă cheia ce urmează să fie ștearsă este mai mică decît cheia rădăc
inii,  
106.     //atunci ea se află în partea stîngă a subarborelui.  
107.     if (key < root->key)  
108.         root->left = deleteNode(root->left, key);  
109.         // Dacă cheia ce urmează să fie ștearsă este mai mare decît cheia 
rădăcinii,  
110.         // atunci ea se află în partea dreaptă a subarborelui.  
111.     else if (key > root->key)  
112.         root->right = deleteNode(root->right, key);  
113.         // dacă cheiea ce urmează a fi ștearsă este acceași ca și rădăcina 
 
114.         // o ștergem  
115.     else {  
116.         // nod cu un singur copil  
117.         if (root->left == NULL) {  
118.             struct node *temp = root->right;  
119.             free(root);  
120.             return temp;  
121.         } else if (root->right == NULL) {  
122.             struct node *temp = root->left;  
123.             free(root);  
124.             return temp;  
125.         }  
126.         // nod cu 2 copii: primim succesorul(iordine) (cel mai mic  
127.         // în subarborele drept  
128.         struct node* temp = minValueNode(root->right);  
129.         // copiem succesorul în acest nod  
130.         root->key = temp->key;  
131.         // ștergem succesorul  
132.         root->right = deleteNode(root->right, temp->key);  
133.     }  
134.     return root;  
135. }  
136.   
137. /* 
138.  * Funcție ce găsește nodul cu valoarea minimă. 
139.  */  
140. struct node * minValueNode(struct node* node) {  
141.     struct node* current = node;  
142.     while (current->left != NULL) {  
143.         current = current->left;  
144.     }  
145.     return current;  
146. }  

 Rezultatul execuției:

Structura arborelui inițial.

Structura arborelui după ștergerea elementului G.

Rezultatul calculării timpului de execuție a programului.


Sarcina 2. Într-un graf orientat să se afle dacă există un arbore parțial de cost minim.
Dacă există să se afle care este vîrful acestuia.
Pentru rezolvarea acestei sarcini voi folosi algoritmul lui Kruskal. Algoritmul lui
Kruskal este un algoritm în teoria grafurilor care găsește arborele parțial de cost
minim pentru un graf conex ponderat. Cu alte cuvinte, găsește submulțimea muchiilor
ce formează un arbore care include toate vîrfurile și care este minimizat din punct de
vedere al costului. Dacă graful nu este conex, atunci algoritmul găsește un arbore
parțial de cost minim pentu fiecare componentă conexă. Algoritmul lui Kruskal este
un exemplu de algoritm greedy.Algoritmul funcționează în felul următor:
1. Start.
2. Crează lista arcelor grafului cu adăugarea ponderilor.
3. Soartază lista arcelor în dependență de pondere crescător.
4. Modelează nodurile pentru a creaz scheletul arborelui de cost minim.
5. Accesează arcul din topul listei (arcul cu ponderea minimă).
6. Șterge arcul selectat din listă.
7. Conectează nodurile prin intermediul arcului dat. Dacă la conectare se
obține un ciclu, atunci renunță la acest arc.
8. Repetăm pașii 5 – 7, până cînd n-1 arce sunt adăugate sau lista arcelor este
plină.
9. Return.
 Fișierul cu date:

 Listingul programului:
1. //  
2. // Created by Victor Rusu on 4/29/17.  
3. //  
4.   
5. #include<stdio.h>  
6. #include <stdlib.h>  
7. //Culori  
8. #define KNRM  "\x1B[0m"  
9. #define KRED  "\x1B[31m"  
10.#define KGRN  "\x1B[32m"  
11.#define KBLU  "\x1B[34m"  
12.#define MAX 30  
13.  
14.typedef struct edge {  
15.    int u,v,w;  
16.}edge;  
17.  
18.typedef struct edgelist {  
19.    edge data[MAX];  
20.    int n;  
21.}edgelist;  
22.  
23.edgelist elist;  
24.  
25.int adjMatrix[MAX][MAX],n;  
26.edgelist splist;  
27.  
28.void kruskalAlgorithm();  
29.int find(int belongs[],int vertexno);  
30.void uneste(int belongs[],int c1,int c2);  
31.void sort();  
32.void print();  
33.void displayAdjMatrix(int n);  
34.  
35.int main() {  
36.  
37.    FILE *input;  
38.  
39.    int source, destination, weight;  
40.    input = fopen("/Users/victorrusu/Documents/cDev/SDA_L/lab524","r");  
41.    if(input==NULL){  
42.        printf("Eroare accesare fișier...");  
43.        exit(1);  
44.    }  
45.  
46.    printf("\nIntroduceți numărul de noduri: ");  
47.    scanf("%d",&n);  
48.  
49.    printf("Rezultatul citirii datelor din fișier:\n");  
50.    while (fscanf(input,"%d %d %d",&source,&destination,&weight)>0){  
51.        printf("Sursa-> %d, Destinația-> %d, Ponderea-> %d\n
",source,destination,weight);  
52.        adjMatrix[source][destination] = weight;  
53.    }  
54.  
55.    displayAdjMatrix(n);  
56.    kruskalAlgorithm();  
57.    print();  
58.    return 0;  
59.}  
60.  
61./* 
62. * Implementarea algoritmului lui Kruskal pentru 
63. *      determinarea arborelui de cost minim. 
64. */  
65.void kruskalAlgorithm() {  
66.    int belongs[MAX],i,j,cno1,cno2;  
67.    elist.n=0;  
68.    for(i=1;i<n;i++) {  
69.        for (j = 0; j < i; j++) {  
70.            if (adjMatrix[i][j] != 0) {  
71.                elist.data[elist.n].u = i;  
72.                elist.data[elist.n].v = j;  
73.                elist.data[elist.n].w = adjMatrix[i][j];  
74.                elist.n++;  
75.            }  
76.        }  
77.    }  
78.    sort();  
79.    for(i=0;i<n;i++) {  
80.        belongs[i] = i;  
81.    }  
82.    splist.n=0;  
83.    for(i=0;i<elist.n;i++) {  
84.        cno1=find(belongs,elist.data[i].u);  
85.        cno2=find(belongs,elist.data[i].v);  
86.        if(cno1!=cno2) {  
87.            splist.data[splist.n]=elist.data[i];  
88.            splist.n=splist.n+1;  
89.            uneste(belongs,cno1,cno2);  
90.        }  
91.    }  
92.}  
93.  
94./* 
95. * Funcție ce întoarce numărul vîrfului. 
96. */  
97.int find(int belongs[],int vertexno) {  
98.    return (belongs[vertexno]);  
99.}  
100.   
101. void uneste(int belongs[],int c1,int c2) {  
102.     int i;  
103.     for(i=0;i<n;i++) {  
104.         if (belongs[i] == c2) {  
105.             belongs[i] = c1;  
106.         }  
107.     }  
108. }  
109.   
110. /* 
111.  * Sortează date. 
112.  */  
113. void sort() {  
114.     int i,j;  
115.     edge temp;  
116.     for(i=1;i<elist.n;i++) {  
117.         for (j = 0; j < elist.n - 1; j++) {  
118.             if (elist.data[j].w > elist.data[j + 1].w) {  
119.                 temp = elist.data[j];  
120.                 elist.data[j] = elist.data[j + 1];  
121.                 elist.data[j + 1] = temp;  
122.             }  
123.         }  
124.     }  
125. }  
126.   
127. /* 
128.  * Funcție ce afișează arcele ce constuie arborele 
129.  *      de cost minim și ponderea acestuia. 
130.  */  
131. void print() {  
132.     printf("%s+ ------------------------------------- +%s",KRED,KNRM);  
133.     printf("\n%s+ ------  Arbore de cost minim  ------- +%s",KRED,KNRM);  
134.     printf("\n%s+ ------------------------------------- +%s",KRED,KNRM);  
135.     printf("\n%s+    Sursa  |  Destinația  |  Ponderea  +%s",KRED,KNRM);  
136.     printf("\n%s+ ------------------------------------- +%s",KRED,KNRM);  
137.     int i,cost=0;  
138.     for(i=0;i<splist.n;i++) {  
139.         printf("\n%s+     %s%d%s     |      %s%d%s       |      %s%d%s     +", 
KRED, KBLU, splist.data[i].u, KRED,  
140.                KBLU, splist.data[i].v, KRED, KBLU, splist.data[i].w, KRED, KNR
M);  
141.         cost=cost+splist.data[i].w;  
142.     }  
143.     printf("\n%s+ ------------------------------------- +%s",KRED,KNRM);  
144.     printf("\n%s+ %sArborele de cost minim = %d%s           +
%s",KRED,KGRN,cost,KRED,KNRM);  
145.     printf("\n%s+ ------------------------------------- +%s",KRED,KNRM);  
146.   
147. }  
148.   
149. /* 
150.  * Afișează matricea de adiacență formată ca 
151.  *      urmare a citirii datelor din fișier. 
152.  */  
153. void displayAdjMatrix(int n){  
154.     int i,j;  
155.     printf("\nMatricea de adiacență a grafului:\n");  
156.     printf("  ");  
157.     for(i=0; i<n; i++){  
158.         printf("%s%d%s ",KRED,i,KNRM);  
159.     }  
160.     printf("\n");  
161.     for(i=0;i<n;i++) {  
162.         printf("%s%d%s ",KRED,i,KNRM);  
163.         for (j = 0; j < n; j++) {  
164.             printf("%d ", adjMatrix[i][j]);  
165.         }  
166.         printf("\n");  
167.     }  
168. }  
 Rezultatul execuției:

Concluzie
Elaborînd această lucrare practică am analizat prelucrarea structurilor de date ce
definesc arbori. Am studiat și însușit materialul teoretic pentru evidențierea esențialului
prelucrării arborilor în elaborarea modelelor soluției, analizînd exemplele din indicații
metodice. Am analizat tehnica modelării și programării eficiente pentru diverse
compartimente ale diferitor situații cu diverse argumentări și modele de structuri de date ce
definesc arbori. La fel mam facut cunoscut cu organigramele care ne dau posibilitate de a
înțelege structura și modul de lucru al arborilor.

S-ar putea să vă placă și