Você está na página 1de 9

#include <stdio.

h>
#include <stdlib.h>
/* ponha valor 0 para desabilitar, 1 para habilitar */
#define DEBUG 1
/* Definicao de um no */
struct NoAVL {
int chave;
int bal;
/* altura(dir) - altura(esq) */
struct NoAVL *esq, *dir;
};
typedef struct NoAVL NoAVL;
/* Cria um novo no com chave k */
NoAVL *Novo(int k) {
NoAVL *p = malloc(sizeof(NoAVL));
p->esq = p->dir = NULL;
p->chave = k;
p->bal = 0;
return p;
}
/* Libera os nohs de uma arvore binaria */
void FreeTree(NoAVL *r) {
if (r != NULL) {
NoAVL *esq = r->esq, *dir = r->dir;
free(r);
FreeTree(esq);
FreeTree(dir);
}
}

/* Funcoes auxiliares para imprimir uma arvore binaria */


void ImprimeChave(int k, int b) {
int i;
if (b) {
for (i=0; i<b-1; i++)
printf("|\t");
printf("|-------%d\n",k);
}
else printf("%d\n",k);
}
void ImprimeArvAVL(NoAVL *r, int b) {
if (r == NULL)
return;
ImprimeArvAVL(r->dir, b+1);
ImprimeChave(r->chave, b);
ImprimeArvAVL(r->esq, b+1);
}

/* Verifica se *r eh uma
arvore AVL e se os campos bal esta corretos */
/* A variavel altura recebe a altura da arvore */
/* Usado apenas para debugar o programa */
int AuxEhAVL(NoAVL *r, int *altura) {
/* Exercicio. Complete o codigo! */
}

/* Rotacao a direita (ou LL). Caso 3a na insercao a esquerda */


void RD(NoAVL **r) {
NoAVL *p = *r, *q = p->esq;
p->esq = q->dir;
q->dir = p;
*r = q;
}
/* Rotacao a esquerda (ou RR). Caso 3a na insercao a direita */
void RE(NoAVL **r) {
NoAVL *p = *r, *q = p->dir;
p->dir = q->esq;
q->esq = p;
*r = q;
}
/* Rotacao Dupla EsqDir (ou LR). Caso 3b na insercao a esquerda */
void RED(NoAVL **r) {
NoAVL *p = *r, *q = p->esq, *t = q->dir;
p->esq =
q->dir =
t->esq =
t->dir =
*r = t;

t->dir;
t->esq;
q;
p;

}
/* Rotacao Dupla DirEsq (ou RL). Caso 3b na insercao a direita */
void RDE(NoAVL **r) {
NoAVL *p = *r, *q = p->dir, *t = q->esq;
p->dir =
q->esq =
t->esq =
t->dir =
*r = t;

t->esq;
t->dir;
p;
q;

/* Funcao auxiliar de insercao: recebe uma arvore AVL, uma chave k */


/* e uma variavel cresceu. */
/* Se a chave k esta na arvore devolve 0. */
/* Caso contrario, insere a chave na arvore. */
/* A variavel cresceu indica se a altura aumentou apos a insercao. */
int Insere(NoAVL **r, int k, int *cresceu) {
if (*r == NULL) {
*r = Novo(k);
*cresceu = 1;
return 1;
}
if ((*r)->chave == k)
return 0;
if ((*r)->chave > k) {
if (Insere(&(*r)->esq, k, cresceu)) { /* insercao na subarvore esquerda */
if (*cresceu) {
switch ((*r)->bal) {
case +1:
/* Caso 1 */
(*r)->bal = 0;
*cresceu = 0;
break;
case 0:
/* Caso 2 */
(*r)->bal = -1;
break;
case -1:
if ((*r)->esq->bal == -1) {
/* Caso 3a */
RD(r);
(*r)->dir->bal = 0;
}
else {
/* Caso 3b */
RED(r);
NoAVL *e = (*r)->esq, *d = (*r)->dir;
switch ((*r)->bal) {
case +1:
e->bal = -1;
d->bal = 0;
break;
case 0:
e->bal = 0;
d->bal = 0;
break;
case -1:
e->bal = 0;
d->bal = 1;
break;
} /* switch */
4

}
(*r)->bal = 0;
*cresceu = 0;
} /* switch */
} /* if (*cresceu) */
return 1;
} /* if (Insere(...)) */
else return 0;
}
else {
/* insercao a direita */
/* Exercicio. Complete o codigo! */
}
}

/* Funcao principal de insercao. */


/* Devolve 0 se a chave esta na arvore senao devolve 1 */
int InsereAVL(NoAVL **r, int k) {
int cresceu;
return Insere(r, k, &cresceu);
}

/* Funcao auxiliar de remocao em arvores AVL: recebe uma arvore AVL, uma chave k */
/* e uma variavel diminuiu. */
/* Se a chave nao esta na arvore entao devolve 0. */
/* Caso contrario, remove o no da arvore e devolve 1. */
/* A variavel diminuiu indica se a altura da arvore diminuiu apos a remocao. */
int Remove(NoAVL **r, int k, int *diminuiu) {
NoAVL *q;
if (*r == NULL) return 0;
if ((*r)->chave > k) {
if (Remove(&(*r)->esq, k, diminuiu)) { /* remocao a esquerda */
Hell:
if (*diminuiu) {
switch ((*r)->bal) {
case 0:
(*r)->bal = 1;
/* caso 2 */
*diminuiu = 0;
break;
case -1:
/* caso 3 */
(*r)->bal = 0;
break;
case +1:
/* caso 4 */
q = (*r)->dir;
switch(q->bal) {
case +1:
/* casos 4a e 4b */
case 0:
RE(r);
(*r)->bal--;
if ((*r)->bal == -1) /* caso 4a */
*diminuiu = 0;
else (*r)->esq->bal = 0;
break;
case -1:
/* caso 4c */
RDE(r);
NoAVL *e = (*r)->esq, *d = (*r)->dir;
switch((*r)->bal) {
case -1:
e->bal = 0;
d->bal = +1;
break;
case 0:
e->bal = 0;
d->bal = 0;
break;
case +1:
6

e->bal = -1;
d->bal = 0;
break;
} /*switch */
(*r)->bal = 0;
}
} /* switch */
} /* if (*diminuiu) */
return 1;
}
else return 0;
}
if ((*r)->chave < k) {
/* insercao a direita */
/* Exercicio. Complete o codigo! */
}
/* Aqui (*r)->chave == k */
if ((*r)->esq == NULL || (*r)->dir == NULL) {
if ((*r)->esq == NULL) {
q = *r;
*r = (*r)->dir;
free(q);
*diminuiu = 1;
return 1;
}
else {
q = *r;
*r = (*r)->esq;
free(q);
*diminuiu = 1;
return 1;
}
}
q = (*r)->esq;
while (q->dir) q = q->dir; /* encontra o predecesor da raiz */
(*r)->chave = q->chave;
/* troca as chave da raiz e seu predecessor */
q->chave = k;
Remove(&(*r)->esq, k, diminuiu);
goto Hell; /* mesmo tratamento do caso da remocao a esquerda */
/* outra opcao eh reescrever o codigo aqui */
}

/* Funcao principal de remocao. */


/* Devolve 0 se a chave NAO esta na arvore senao devolve 1 */
int RemoveAVL(NoAVL **r, int k) {
int diminuiu;
return Remove(r, k, &diminuiu);
}
int main() {
NoAVL *r = NULL; /* MUITO importante! */
char op;
int k;
do {
printf("Insercao e remocao em arvore
printf("(I) Insere um no com chave k
printf("(R) Remove um no com chave k
printf("(P) Imprime a arvore (digite
printd("(S) Sair do programa (digite
printf("Opcao: ");
scanf(" %c", &op);
switch (op) {
case I:
case i:
scanf("%d", &k);
InsereAVL(&r, k);
#ifdef DEBUG
EhAVL(r);
#endif
ImprimeArvAVL(r, 0);
break;
case R:
case r:
scanf("%d", &k);
RemoveAVL(&r, k);
#ifdef DEBUG
EhAVL(r);
#endif
ImprimeArvAVL(r, 0);
break;
case P:
case p:
ImprimeArvAVL(r, 0);
break;
case S:
case s:
break;
default:
8

AVL\n");
(digite i/I k)\n");
(digite r/R k)\n");
p/P)\n");
s/S)\n");

printf("Opcao invalida.\n");
}
} while(op != S && op != s);
return 1;
}

Você também pode gostar