Skip to content

Commit f935c6e

Browse files
committed
commit
1 parent a7bdbaf commit f935c6e

11 files changed

+1096
-0
lines changed

P08/PROG2_2021_P08_Heaps.pdf

56.6 KB
Binary file not shown.

P08/avl.c

+371
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
/*****************************************************************/
2+
/* Arvore AVL | PROG2 | MIEEC | 2017/18 */
3+
/*****************************************************************/
4+
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include "avl.h"
9+
10+
/* declaracao das funcoes utilitarias */
11+
no_avl* avl_pesquisa_impl(no_avl *no, const char *str);
12+
no_avl* avl_insere_impl(no_avl *no, const char *str);
13+
no_avl* avl_remove_impl(no_avl *no, const char *str);
14+
no_avl* avl_no_valormin(no_avl* no);
15+
no_avl* avl_no_valormax(no_avl* no);
16+
void avl_preordem_impl(no_avl *no);
17+
18+
19+
arvore_avl* avl_nova()
20+
{
21+
arvore_avl *avl = (arvore_avl*) malloc(sizeof(arvore_avl));
22+
if(avl == NULL)
23+
return NULL;
24+
25+
avl->raiz = NULL; /* arvore vazia */
26+
27+
return avl;
28+
}
29+
30+
void avl_apaga(arvore_avl* avl)
31+
{
32+
if (!avl) return;
33+
while(avl->raiz != NULL)
34+
{
35+
avl->raiz = avl_remove_impl(avl->raiz, avl->raiz->str);
36+
}
37+
38+
free(avl);
39+
}
40+
41+
no_avl* avl_pesquisa(arvore_avl* avl, const char *str)
42+
{
43+
if(avl == NULL || str == NULL)
44+
return NULL;
45+
46+
return avl_pesquisa_impl(avl->raiz, str);
47+
}
48+
49+
int avl_insere(arvore_avl* avl, const char *str)
50+
{
51+
if(avl == NULL || str == NULL)
52+
return -1;
53+
54+
avl->raiz = avl_insere_impl(avl->raiz, str);
55+
56+
return 0;
57+
}
58+
59+
int avl_remove(arvore_avl* avl, const char *str)
60+
{
61+
if(avl == NULL || str == NULL)
62+
return -1;
63+
64+
avl->raiz = avl_remove_impl(avl->raiz, str);
65+
66+
return 0;
67+
}
68+
69+
const char *avl_min(no_avl* no)
70+
{
71+
if(no == NULL)
72+
return NULL;
73+
74+
return avl_no_valormin(no)->str;
75+
}
76+
77+
const char *avl_max(no_avl* no)
78+
{
79+
if(no == NULL)
80+
return NULL;
81+
82+
return avl_no_valormax(no)->str;
83+
}
84+
85+
void avl_imprime(no_avl* no)
86+
{
87+
if(no == NULL)
88+
return;
89+
90+
avl_preordem_impl(no);
91+
92+
printf("\n");
93+
}
94+
95+
96+
97+
/*************************************************/
98+
/* funcoes utilitarias */
99+
/*************************************************/
100+
101+
/* altura da arvore */
102+
int avl_altura(no_avl *no)
103+
{
104+
if (no == NULL)
105+
return -1;
106+
return no->altura;
107+
}
108+
109+
/* maximo entre dois inteiros */
110+
int max(int a, int b)
111+
{
112+
return (a > b)? a : b;
113+
}
114+
115+
/* cria um novo no dada uma string */
116+
no_avl* avl_novo_no(const char *str)
117+
{
118+
no_avl *no = (no_avl*) malloc(sizeof(no_avl));
119+
no->str = (char*) malloc(sizeof(char)*(strlen(str)+1));
120+
strcpy(no->str, str);
121+
no->esquerda = NULL;
122+
no->direita = NULL;
123+
no->altura = 0; /* novo no e' inicialmente uma folha */
124+
return no;
125+
}
126+
127+
/* roda sub-arvore 'a direita tendo raiz em y */
128+
no_avl* roda_direita(no_avl *y)
129+
{
130+
no_avl *x = y->esquerda;
131+
no_avl *T2 = x->direita;
132+
133+
/* efetua rotacao */
134+
x->direita = y;
135+
y->esquerda = T2;
136+
137+
/* atualiza alturas */
138+
y->altura = max(avl_altura(y->esquerda), avl_altura(y->direita))+1;
139+
x->altura = max(avl_altura(x->esquerda), avl_altura(x->direita))+1;
140+
141+
/* retorna novo no' */
142+
return x;
143+
}
144+
145+
/* roda sub-arvore 'a esquerda tendo raiz em x */
146+
no_avl* roda_esquerda(no_avl *x)
147+
{
148+
no_avl *y = x->direita;
149+
no_avl *T2 = y->esquerda;
150+
151+
/* efetua rotacao */
152+
y->esquerda = x;
153+
x->direita = T2;
154+
155+
/* atualiza alturas */
156+
x->altura = max(avl_altura(x->esquerda), avl_altura(x->direita))+1;
157+
y->altura = max(avl_altura(y->esquerda), avl_altura(y->direita))+1;
158+
159+
/* retorna novo no' */
160+
return y;
161+
}
162+
163+
/* calcula fator de balanceamento */
164+
int calc_balanceamento(no_avl *N)
165+
{
166+
if (N == NULL)
167+
return 0;
168+
return avl_altura(N->direita) - avl_altura(N->esquerda);
169+
}
170+
171+
no_avl* avl_pesquisa_impl(no_avl* no, const char *str)
172+
{
173+
if(no == NULL)
174+
return NULL;
175+
176+
if(strcmp(str, no->str) < 0)
177+
return avl_pesquisa_impl(no->esquerda, str);
178+
179+
else if(strcmp(str, no->str) > 0)
180+
return avl_pesquisa_impl(no->direita, str);
181+
182+
else
183+
return no;
184+
}
185+
186+
no_avl* avl_insere_impl(no_avl *no, const char *str)
187+
{
188+
/* 1. efetua insercao normal de arvore binaria de pesquisa */
189+
if (no == NULL)
190+
return avl_novo_no(str);
191+
192+
if (strcmp(str, no->str) < 0)
193+
no->esquerda = avl_insere_impl(no->esquerda, str);
194+
else if(strcmp(str, no->str) > 0)
195+
no->direita = avl_insere_impl(no->direita, str);
196+
else {
197+
return no;
198+
}
199+
200+
/* 2. atualiza a altura deste no ancestral */
201+
no->altura = max(avl_altura(no->esquerda), avl_altura(no->direita)) + 1;
202+
203+
/* 3. calcula o fator de balanceamento deste no ancestral para verificar
204+
se deixou de estar balanceado */
205+
int balance = calc_balanceamento(no);
206+
207+
/* se o no deixou de estar balanceado, existem 4 casos */
208+
209+
if (balance > 1) {
210+
/* Arvore e' right-heavy */
211+
if (calc_balanceamento(no->direita) < 0) {
212+
/* Sub-arvore direita é left-heavy */
213+
/* Rotacao RL */
214+
no->direita = roda_direita(no->direita);
215+
return roda_esquerda(no);
216+
} else {
217+
/* Rotacao L */
218+
return roda_esquerda(no);
219+
}
220+
}
221+
else if (balance < -1) {
222+
/* Arvore e' left-heavy */
223+
if (calc_balanceamento(no->esquerda) > 0) {
224+
/* Sub-arvore esquerda é right-heavy */
225+
/* Rotacao LR */
226+
no->esquerda = roda_esquerda(no->esquerda);
227+
return roda_direita(no);
228+
} else {
229+
/* Rotacao R */
230+
return roda_direita(no);
231+
}
232+
}
233+
/* caso esteja balanceada retorna o apontador para o no (inalterado) */
234+
return no;
235+
}
236+
237+
/* dada uma arvore binaria de pesquisa, retorna o no' com o valor minimo
238+
que se pode encontrar nessa arvore */
239+
no_avl* avl_no_valormin(no_avl* no)
240+
{
241+
no_avl* curr = no;
242+
243+
/* percorre a arvore para encontrar o filho mais 'a esquerda */
244+
while (curr->esquerda != NULL)
245+
curr = curr->esquerda;
246+
247+
return curr;
248+
}
249+
250+
/* dada uma arvore binaria de pesquisa, retorna o no' com o valor maximo
251+
que se pode encontrar nessa arvore */
252+
no_avl* avl_no_valormax(no_avl* no)
253+
{
254+
no_avl* curr = no;
255+
256+
/* percorre a arvore para encontrar o filho mais 'a direita */
257+
while (curr->direita != NULL)
258+
curr = curr->direita;
259+
260+
return curr;
261+
}
262+
263+
no_avl* avl_remove_impl(no_avl* no, const char *str)
264+
{
265+
/* 1. efetua remocao normal de arvore binaria de pesquisa */
266+
267+
if (no == NULL)
268+
return no;
269+
270+
/* se a str a ser removida é menor do que a str da raiz,
271+
entao esta' na sub-arvore esquerda */
272+
if ( strcmp(str, no->str) < 0 )
273+
no->esquerda = avl_remove_impl(no->esquerda, str);
274+
275+
/* se a str a ser removida é maior do que a str da raiz,
276+
entao esta' na sub-arvore direita */
277+
else if( strcmp(str, no->str) > 0 )
278+
no->direita = avl_remove_impl(no->direita, str);
279+
280+
/* se a str a ser removida é igual a str da raiz,
281+
entao e' este no a remover */
282+
else
283+
{
284+
/* no' com apenas um filho ou sem filhos */
285+
if( (no->esquerda == NULL) || (no->direita == NULL) )
286+
{
287+
no_avl *temp = no->esquerda ? no->esquerda : no->direita;
288+
289+
/* caso sem filhos */
290+
if(temp == NULL)
291+
{
292+
temp = no;
293+
no = NULL;
294+
}
295+
else /* caso de um filho */
296+
{
297+
/* copia os conteudos do filho que não está vazio */
298+
no->str = realloc(no->str, (strlen(temp->str)+1)*sizeof(char));
299+
strcpy(no->str, temp->str);
300+
no->esquerda = temp->esquerda;
301+
no->direita = temp->direita;
302+
no->altura = temp->altura;
303+
}
304+
305+
free(temp->str);
306+
free(temp);
307+
}
308+
else
309+
{
310+
/* no' com dois filhos: obtem sucessor em-ordem (menor da arvore direita) */
311+
no_avl* temp = avl_no_valormin(no->direita);
312+
313+
/* copia o valor em.ordem do sucessor para este no' */
314+
no->str = realloc(no->str, (strlen(temp->str)+1)*sizeof(char));
315+
strcpy(no->str, temp->str);
316+
317+
/* apaga o sucessor em-ordem */
318+
no->direita = avl_remove_impl(no->direita, temp->str);
319+
}
320+
}
321+
322+
/* se a arvore tinha apenas um no, então retorna */
323+
if (no == NULL)
324+
return no;
325+
326+
/* 2. atualiza a altura do no corrente */
327+
no->altura = max(avl_altura(no->esquerda), avl_altura(no->direita)) + 1;
328+
329+
/* 3. calcula o fator de balanceamento deste no ancestral para verificar
330+
se deixou de estar balanceado */
331+
int balance = calc_balanceamento(no);
332+
333+
/* se o no deixou de estar balanceado, existem 4 casos */
334+
335+
if (balance > 1) {
336+
/* Arvore e' right-heavy */
337+
if (calc_balanceamento(no->direita) < 0) {
338+
/* Sub-arvore direita é left-heavy */
339+
/* Rotacao RL */
340+
no->direita = roda_direita(no->direita);
341+
return roda_esquerda(no);
342+
} else {
343+
/* Rotacao L */
344+
return roda_esquerda(no);
345+
}
346+
}
347+
else if (balance < -1) {
348+
/* Arvore e' left-heavy */
349+
if (calc_balanceamento(no->esquerda) > 0) {
350+
/* Sub-arvore esquerda é right-heavy */
351+
/* Rotacao LR */
352+
no->esquerda = roda_esquerda(no->esquerda);
353+
return roda_direita(no);
354+
} else {
355+
/* Rotacao R */
356+
return roda_direita(no);
357+
}
358+
}
359+
/* caso esteja balanceada retorna o apontador para o no (inalterado) */
360+
return no;
361+
}
362+
363+
void avl_preordem_impl(no_avl* no)
364+
{
365+
if(no == NULL)
366+
return;
367+
368+
printf("%s ", no->str);
369+
avl_preordem_impl(no->esquerda);
370+
avl_preordem_impl(no->direita);
371+
}

0 commit comments

Comments
 (0)