Skip to content

Commit 5173399

Browse files
committed
commit
1 parent 9e408e6 commit 5173399

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+4244
-0
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.

MT_2/PROG2_1617_MT2/prob1/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)