5 de novembro de 2009

Imprime árvore

Para ajudar a depurar os programas, fiz este código que imprime uma árvore (que não seja muito grande). Realmente ajuda bastante.
Existe uma solução para grafos que se chama Graphviz.

/*#include "imprimeArvore.h"*/
#include
#include

#define OK 0
#define OVERFLOW 1
#define UNDERFLOW -1

typedef struct cel
{
char info;
struct cel * filhoEsq;
struct cel * filhoDir;
} noh;

/* Esta é a estrutura de um elemento da fila */
typedef struct elementoDaFila
{
char info;
noh *filhoEsq;
noh *filhoDir;

struct elementoDaFila *prox;
} enfileirado;

/* Funções de manipulação da fila */

void copiaCampos(noh origem, enfileirado* destino)
{
if(destino == NULL)
fprintf(stderr, "\n\nErro: o destino da cópia é null\n\n");
else
{
destino->info = origem.info;
destino->filhoEsq = origem.filhoEsq;
destino->filhoDir = origem.filhoDir;
}
}

void copiaCampos2(enfileirado origem, noh* destino)
{
if(destino == NULL)
fprintf(stderr, "\n\nErro: o destino da cópia é null\n\n");
else
{
destino->info = origem.info;
destino->filhoEsq = origem.filhoEsq;
destino->filhoDir = origem.filhoDir;
}
}

void enfileira(noh novoNo, enfileirado** primeiro, enfileirado** ultimo)
{
enfileirado* novo = malloc(sizeof(enfileirado));
copiaCampos(novoNo, novo);
if(filaVazia(*primeiro, *ultimo))
{
*primeiro = novo;
*ultimo = novo;
}
else
{
(*ultimo)->prox = novo;
*ultimo = novo;
}
}

int proximo(noh* devolvido, enfileirado** primeiro, enfileirado** ultimo)
{
if(!filaVazia(*primeiro, *ultimo))
{
copiaCampos2(**primeiro, devolvido);
if((*primeiro)->prox == NULL)
*ultimo = NULL;
*primeiro = (*primeiro)->prox;
return OK;
}
else
{
devolvido = NULL;
return UNDERFLOW;
}
}

int filaVazia(enfileirado* primeiro, enfileirado* ultimo)
{
return primeiro == NULL;
}


/* funções auxiliares */
void imprimeVarios(char c, int quantidade)
{
while(quantidade > 0)
{
printf("%c", c);
quantidade--;
}
}

int maximo(int um, int outro)
{
if(um > outro)
return um;
return outro;
}


int achaAltura(noh raiz)
{
int alturaDir;
int alturaEsq;

alturaDir = 0;
alturaEsq = 0;

if(raiz.filhoEsq != NULL)
alturaEsq = achaAltura(*(raiz.filhoEsq));
if(raiz.filhoDir != NULL)
alturaDir = achaAltura(*(raiz.filhoDir));

return maximo(alturaEsq, alturaDir) + 1;
}

/* só serve pra expoente não-negativo */
int potencia(int base, int expoente)
{
if(expoente == 0) /* supondo que zero elevado a zero é 1 */
return 1;
if(base == 0)
return 0;
return base*potencia(base, expoente-1);
}

/* Função para a impressão de uma árvore binária */
void imprimeArvoreBinaria(noh raiz)
{
int i;
int nivel; /* nível atual */
int altura;
int numFolhas; /* número de folhas que teria
a árvore se ela fosse cheia */
int d; /* esta variável guarda o número de folhas
que teria uma árvore cheia com altura igual
a altura da árvore - nível atual.*/

/* variáveis da fila */
enfileirado *primeiro;
enfileirado *ultimo;

noh *temp;
noh *espaco; /* usado para "preencher" buracos na árvore, pois ela pode
não ser cheia, mas devemos ter um nó fictício no lugar*/

espaco = malloc(sizeof(noh));
espaco->info = ' ';
espaco->filhoEsq = NULL;
espaco->filhoDir = NULL;

temp = malloc(sizeof(noh));

primeiro = NULL;
ultimo = NULL;

altura = achaAltura(raiz);
numFolhas = potencia(2, altura-1);

d = numFolhas;

nivel = 1;
enfileira(raiz, &primeiro, &ultimo);

while(nivel <= altura)
{
/* gambiarra's.. */
if(d == 1)
d = 0;

/* imprimindo a linha com as infos */
for(i = 0; i < potencia(2,nivel-1); i++)
{
if(proximo(temp, &primeiro, &ultimo) == UNDERFLOW)
fprintf(stderr, "poatz... underflow mano...");

imprimeVarios(' ', d);
if(temp->info == ' ')
imprimeVarios(' ', d-2);
else
imprimeVarios('_', d-2);
if(temp == NULL || temp->info == '\0')
printf(" ");
else
printf("%c", temp->info);
if(temp->info == ' ')
imprimeVarios(' ', d-2);
else
imprimeVarios('_', d-2);

/* se for a última iteração... */
if(i == potencia(2,nivel-1)-1)
printf("\n");
else
imprimeVarios(' ', d+3);

/* enfileirando os filhos */
if(temp->filhoEsq == NULL)
enfileira(*espaco, &primeiro, &ultimo);
else
enfileira(*(temp->filhoEsq), &primeiro,&ultimo);
if(temp->filhoDir == NULL)
enfileira(*espaco, &primeiro, &ultimo);
else
enfileira(*(temp->filhoDir), &primeiro,&ultimo);
}

/* imprimindo a linha com os "galhos" da árvores */
if(d != 0) /* gambiarra's */
{
for(i = 0; i < potencia(2,nivel-1); i++)
{
imprimeVarios(' ', d-1);
printf("/");
imprimeVarios(' ', 2*d-3);
printf("\\");

/* se for a última iteração, pula linha */
if(i == potencia(2,nivel-1)-1)
printf("\n");
else
imprimeVarios(' ', d+2);
}
}
nivel++;
d = d/2;
}
}


int main()
{
noh* varre;
noh* raiz = malloc(sizeof(noh));

raiz->info = 'A';
raiz->filhoEsq = malloc(sizeof(noh));
raiz->filhoDir = malloc(sizeof(noh));

varre = raiz->filhoEsq;
varre->info = 'B';
varre->filhoEsq = malloc(sizeof(noh));
varre->filhoDir = malloc(sizeof(noh));

varre = raiz->filhoDir;
varre->info = 'C';
varre->filhoEsq = malloc(sizeof(noh));
varre->filhoDir = malloc(sizeof(noh));

varre = (raiz->filhoEsq)->filhoEsq;
varre->info = 'D';
varre->filhoEsq = NULL;
varre->filhoDir = NULL;

varre = (raiz->filhoEsq)->filhoDir;
varre->info = 'E';
varre->filhoEsq = NULL;
varre->filhoDir = NULL;

varre = (raiz->filhoDir)->filhoEsq;
varre->info = 'F';
varre->filhoEsq = NULL;
varre->filhoDir = NULL;

varre = (raiz->filhoDir)->filhoDir;
varre->info = 'G';
varre->filhoEsq = NULL;
varre->filhoDir = NULL;
imprimeArvoreBinaria(*raiz);
return 0;
}


Nenhum comentário:

Postar um comentário