typedef struct nodo{
int valor;
struct nodo *esq, * dir;
} * ABin;-
Uma forma de remover um elemento de uma árvore binária de procura sem aumentar a altura da árvore consiste em substituir o nodo onde esse elemento se encontra pelo menor elemento que se encontra do seu lado direito. Apresente definições das seguintes funções sobre árvores binárias de procura. (a)
ABin removeMenor (ABin *a)que remove o nodo mais à esquerda de uma árvore (retornando esse nodo). (b)void removeRaiz (ABin *a)que remove a raiz de uma árvore não vazia (libertando o correspondente espaço). (c)int removeElem (ABin *a, int x)que remove um elemento de uma árvore binária, libertando o espaço correspondente. A função deverá retornar 0 se o elemento existia na árvore. -
Considere as seguintes definições que rodam uma árvore. Note que ambas as operações preservam a ordem dos elementos (i.e., se forem efectuadas sobre uma árvore de procura, o resultado continua a ser uma árvore de procura).
void rodaEsquerda(ABin *a){
ABin b = (*b)->dir;
(*a)->dir = b->esq;
b->esq = (*a);
*a = b;
}
void rodaDireita(ABin *a){
ABin b = (*a)->esq;
(*a)->esq = b->dir;
b->dir = *a;
*a = b;
}Note ainda que ao efectuar uma destas rotações, o elemento que está na raiz passa para o nivel 1 enquanto que um dos elementos que está no nível 1 passa para o nnível 0. Neste caso dizemos que este último elemento foi promovido.
Usando estas funções defina as seguintes operações sobre árvores binárias de procura.
(d) void promoveMenor (ABin *a) que promove o menor elemento de uma árvore para o nível 0. A árvore resultante não deve aumentar a altura da árvore em mais do que uma unidade.
(e) void promoveMaior (ABin *a) que promove o maior elemento de uma árvore para o nível 0. A árvore resultante não deve aumentar a altura da árvore em mais do que uma unidade.
(f) Apresente uma definição alternativa da função removeMenor descrita na questão 1.
- Uma árvore diz-se equilibrada sse, em cada nodo, o número de nodos à esquerda e à direita não difere em mais do que uma unidade. Uma forma de equilibrar uma árvore consiste em começar por a transformar numa espinha (i.e., uma árvore em que todos os nodos tˆem a sub-árvore da esquerda vazios) e depois equilibrar essa
árvore.
Nas funções que se descrevem abaixo não deve ser feita qualquer alocação de mem´oria; deve-se reorganizar os nodos da árvore de forma a obter o resultado pretendido
(g) Defina uma função
int constroiEspinha (ABin *a)que transforma a árvore *a numa espinha. A função deve retornar o número de nodos da árvore. Sugestão: de forma a tornar esta função mais eficiente, comece por definir uma funçãoint constroiEspinhaAux (ABin *a, ABin *ult)que também coloca e *ult o endereço do nodo mais à direita da árvore produzida. (h) Defina uma funçãoABin equilibraEspinha (ABin *a, int n)que recebe uma espinha *a e um número n e produz uma árvore equilibrada com esses nodos. Em *a fica a árvore construnída e é retornado o endereço dos elementos da espinha que não foram utilizados. (i) Usando as funções anteriores, defina uma funçãovoid equilibra (ABin *a)que equilibra uma árvore.
#include "abin.h"
ABin newABin(int r, ABin e, ABin d) {
ABin a = malloc(sizeof(struct nodo));
if (a != NULL) {
a->valor = r;
a->esq = e;
a->dir = d;
}
return a;
}
ABin RandArvFromArray(int v[], int N) {
ABin a = NULL;
int m;
if (N > 0) {
m = rand() % N;
a = newABin(v[m], RandArvFromArray(v, m),
RandArvFromArray(v + m + 1, N - m - 1));
}
return a;
}
// Questão 1
ABin removeMenor(ABin *a) {
ABin ant = NULL, atual = *a;
while (atual->esq != NULL) {
ant = atual;
atual = atual->esq;
}
if (ant == NULL)
(*a) = atual->dir;
else
ant->esq = atual->dir;
atual->dir = NULL;
return atual;
}
void removeRaiz(ABin *a) {
ABin atual = (*a), sub = NULL;
if (atual->dir == NULL) {
(*a) = atual->esq;
free(atual);
} else {
sub = removeMenor(&(atual->dir));
sub->esq = (*a)->esq;
sub->dir = ((*a)->dir);
(*a) = sub;
free(atual);
}
}
int removeElem(ABin *a, int x) {
ABin atual = *a, ant = NULL;
while (atual != NULL && atual->valor != x) {
ant = atual;
if (x < atual->valor) {
atual = atual->esq;
} else {
atual = atual->dir;
}
}
if (atual == NULL)
return 1;
else if (ant == NULL) {
removeRaiz(a);
return 0;
} else {
((ant->esq) == atual) ? (removeRaiz(&(ant->esq)))
: (removeRaiz(&(ant->dir)));
return 0;
}
}
// Questão 2
void rodaEsquerda(ABin *a) {
ABin b = (*a)->dir;
(*a)->dir = b->esq;
b->esq = (*a);
*a = b;
}
void rodaDireita(ABin *a) {
ABin b = (*a)->esq;
(*a)->esq = b->dir;
b->dir = *a;
*a = b;
}
void promoveMenor(ABin *a) {
ABin atual = *a;
if (atual != NULL && atual->esq != NULL) {
promoveMenor(&(atual->esq));
rodaDireita(a);
}
}
void promoveMaior(ABin *a) {
ABin atual = *a;
if (atual != NULL && atual->dir != NULL) {
promoveMaior(&(atual->dir));
rodaEsquerda(a);
}
}
ABin removeMenorAlt(ABin *a) {
if (*a == NULL)
return NULL;
promoveMenor(a);
ABin menor = *a;
*a = (*a)->dir;
menor->dir = NULL;
return menor;
}
// Questão 3
int constroiEspinhaAux(ABin *a, ABin *ult) {
if (*a == NULL) {
*ult = NULL;
return 0;
}
ABin raizOriginal = *a, ultEsq = NULL, ultDir = NULL;
int nEsq = constroiEspinhaAux(&(raizOriginal->esq), &ultEsq);
if (nEsq > 0) {
ultEsq->dir = raizOriginal;
*a = raizOriginal->esq;
}
int nDir = constroiEspinhaAux(&(raizOriginal->dir), &ultDir);
if (nDir > 0) {
*ult = ultDir;
} else {
*ult = raizOriginal;
}
return nEsq + 1 + nDir;
}
int constroiEspinha(ABin *a) {
ABin ult;
return (constroiEspinhaAux(a, &ult));
}
ABin equilibraEspinha(ABin *a, int n) {
if (n == 0) {
ABin sobra = *a;
*a = NULL;
return sobra;
}
int nEsq = n / 2;
ABin resto = equilibraEspinha(a, nEsq);
ABin raiz = resto;
ABin direita = raiz->dir;
int nDir = n - nEsq - 1;
ABin restoFinal = equilibraEspinha(&direita, nDir);
raiz->esq = *a;
raiz->dir = direita;
*a = raiz;
return restoFinal;
}
void equilibra(ABin *a) {
int n = constroiEspinha(a);
equilibraEspinha(a, n);
}
#include "abin.h"
#include <time.h>
int main() {
int v1[15] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29}, N = 15,
i;
ABin a1, r;
srand(time(NULL));
printf("_______________ Testes _______________\n\n");
// N = rand() % 16;
a1 = RandArvFromArray(v1, N);
printf("________________________________________\n");
printf("Primeira árvore de teste (%d elementos)\n", N);
// dumpABin(a1, N);
/*
printf ("Espinha\n");
constroiEspinha_sol (&a1);
// dumpABin (a1, N);
printf ("Equilibrar espinha\n");
equilibraEspinha_sol (&a1,N);
// dumpABin (a1, N);
*/
i = rand() % N;
printf("Remoção do elemento %d\n", v1[i]);
removeElem(&a1, v1[i]);
// dumpABin(a1, --N);
r = removeMenor(&a1);
printf("Remoção do menor %d\n", r->valor);
// dumpABin(a1, --N);
printf("Remoção da raiz %d\n", a1->valor);
removeRaiz(&a1);
// dumpABin(a1, --N);
// freeABin(a1);
a1 = newABin(v1[7], RandArvFromArray(v1, 7), RandArvFromArray(v1 + 8, 7));
N = 15;
printf("_______________________________________\n");
printf("Segunda árvore de teste (%d elementos)\n", N);
// dumpABin(a1, N);
printf("Rotação à direita\n");
rodaDireita(&a1);
// dumpABin(a1, N);
printf("Rotação à esquerda\n");
rodaEsquerda(&a1);
// dumpABin(a1, N);
printf("Promoção do maior\n");
promoveMaior(&a1);
// dumpABin(a1, N);
printf("Promoção do menor\n");
promoveMenor(&a1);
// dumpABin(a1, N);
printf("\n\n___________ Fim dos testes ___________\n\n");
return 0;
}