Você está na página 1de 14

13.

rvores
W. Celes e J. L. Rangel

Nos captulos anteriores examinamos as estruturas de dados que podem ser chamadas
de unidimensionais ou lineares, como vetores e listas. A importncia dessas estruturas
inegvel, mas elas no so adequadas para representarmos dados que devem ser
dispostos de maneira hierrquica. Por exemplo, os arquivos (documentos) que criamos
num computador so armazenados dentro de uma estrutura hierrquica de diretrios
(pastas). Existe um diretrio base dentro do qual podemos armazenar diversos subdiretrios e arquivos. Por sua vez, dentro dos sub-diretrios, podemos armazenar outros
sub-diretrios e arquivos, e assim por diante, recursivamente. A Figura 13.1 mostra uma
imagem de uma rvore de diretrio no Windows 2000.

Figura 13.1: Um exemplo de rvore de diretrio.

Neste captulo, vamos introduzir rvores, que so estruturas de dados adequadas para a
representao de hierarquias. A forma mais natural para definirmos uma estrutura de
rvore usando recursividade. Uma rvore composta por um conjunto de ns. Existe
um n r , denominado raiz, que contm zero ou mais sub-rvores, cujas razes so
ligadas diretamente a r. Esses ns razes das sub-rvores so ditos filhos do n pai, r.
Ns com filhos so comumente chamados de ns internos e ns que no tm filhos so
chamados de folhas, ou ns externos. tradicional desenhar as rvores com a raiz para
cima e folhas para baixo, ao contrrio do que seria de se esperar. A Figura 13.2
exemplifica a estrutura de uma rvore.
n raiz

...

sub-rvores

Figura 13.2: Estrutura de rvore.

Observamos que, por adotarmos essa forma de representao grfica, no


representamos explicitamente a direo dos ponteiros, subentendendo que eles apontam
sempre do pai para os filhos.
Estruturas de Dados PUC-Rio

12-1

O nmero de filhos permitido por n e as informaes armazenadas em cada n


diferenciam os diversos tipos de rvores existentes. Neste captulo, estudaremos dois
tipos de rvores. Primeiro, examinaremos as rvores binrias, onde cada n tem, no
mximo, dois filhos. Depois examinaremos as chamadas rvores genricas, onde o
nmero de filhos indefinido. Estruturas recursivas sero usadas como base para o
estudo e a implementao das operaes com rvores.

13.1. rvores binrias


Um exemplo de utilizao de rvores binrias est na avaliao de expresses. Como
trabalhamos com operadores que esperam um ou dois operandos, os ns da rvore para
representar uma expresso tm no mximo dois filhos. Nessa rvore, os ns folhas
representam operandos e os ns internos operadores. Uma rvore que representa, por
exemplo a expresso (3+6)*(4-1)+5 ilustrada na Figura 13.3.
+

+
3

Figura 13.3: rvore da expresso: (3+6) * (4-1) + 5.

Numa rvore binria, cada n tem zero, um ou dois filhos. De maneira recursiva,
podemos definir uma rvore binria como sendo:
uma rvore vazia; ou
um n raiz tendo duas sub-rvores, identificadas como a sub-rvore da
direita (sad) e a sub-rvore da esquerda (sae).
A Figura 13.4 ilustra a definio de rvore binria. Essa definio recursiva ser usada
na construo de algoritmos, e na verificao (informal) da correo e do desempenho
dos mesmos.

Estruturas de Dados PUC-Rio

12-2

raiz
vazia

sae

sad

Figura 13.4: Representao esquemtica da definio da estrutura de rvore binria.

A Figura 13.5 a seguir ilustra uma estrutura de rvore binria. Os ns a, b, c, d, e, f


formam uma rvore binria da seguinte maneira: a rvore composta do n a, da subrvore esquerda formada por b e d, e da sub-rvore direita formada por c, e e f. O n
a representa a raiz da rvore e os ns b e c as razes das sub-rvores. Finalmente, os ns
d, e e f so folhas da rvore.

a
b

c
d

Figura 13.5: Exemplo de rvore binria

Para descrever rvores binrias, podemos usar a seguinte notao textual: a rvore vazia
representada por <>, e rvores no vazias por <raiz sae sad>. Com essa notao,
a
rvore
da
Figura
13.5

representada
por:
<a<b<><d<><>>><c<e<><>><f<><>>>>.

Pela definio, uma sub-rvore de uma rvore binria sempre especificada como
sendo a sae ou a sad de uma rvore maior, e qualquer das duas sub-rvores pode ser
vazia. Assim, as duas rvores da Figura 13.6 so distintas.

a
b

a
b

Figura 13.6: Duas rvores binrias distintas.

Isto tambm pode ser visto pelas representaes textuais das duas rvores, que so,
respectivamente: <a <b<><>> <> > e <a <> <b<><>> >.
Estruturas de Dados PUC-Rio

12-3

Uma propriedade fundamental de todas as rvores que s existe um caminho da raiz


para qualquer n. Com isto, podemos definir a altura de uma rvore como sendo o
comprimento do caminho mais longo da raiz at uma das folhas. Por exemplo, a altura
da rvore da Figura 13.5 2, e a altura das rvores da Figura 13.6 1. Assim, a altura
de uma rvore com um nico n raiz zero e, por conseguinte, dizemos que a altura de
uma rvore vazia negativa e vale -1.
Exerccio: Mostrar que uma rvore binria de altura h tem, no mnimo, h+1 ns, e, no
mximo, 2h+1 1.
Representao em C
Anlogo ao que fizemos para as demais estruturas de dados, podemos definir um tipo
para representar uma rvore binria. Para simplificar a discusso, vamos considerar que
a informao que queremos armazenar nos ns da rvore so valores de caracteres
simples. Vamos inicialmente discutir como podemos representar uma estrutura de
rvore binria em C. Que estrutura podemos usar para representar um n da rvore?
Cada n deve armazenar trs informaes: a informao propriamente dita, no caso um
caractere, e dois ponteiros para as sub-rvores, esquerda e direita. Ento a estrutura
de C para representar o n da rvore pode ser dada por:
struct arv {
char info;
struct arv* esq;
struct arv* dir;
};

Da mesma forma que uma lista encadeada representada por um ponteiro para o
primeiro n, a estrutura da rvore como um todo representada por um ponteiro para o
n raiz.
Como acontece com qualquer TAD (tipo abstrato de dados), as operaes que fazem
sentido para uma rvore binria dependem essencialmente da forma de utilizao que se
pretende fazer da rvore. Nesta seo, em vez de discutirmos a interface do tipo abstrato
para depois mostrarmos sua implementao, vamos optar por discutir algumas
operaes mostrando simultaneamente suas implementaes. Ao final da seo
apresentaremos um arquivo que pode representar a interface do tipo. Nas funes que se
seguem, consideraremos que existe o tipo Arv definido por:
typedef struct arv Arv;

Como veremos as funes que manipulam rvores so, em geral, implementadas de


forma recursiva, usando a definio recursiva da estrutura.
Vamos procurar identificar e descrever apenas operaes cuja utilidade seja a mais geral
possvel. Uma operao que provavelmente dever ser includa em todos os casos a
inicializao de uma rvore vazia. Como uma rvore representada pelo endereo do
n raiz, uma rvore vazia tem que ser representada pelo valor NULL. Assim, a funo
que inicializa uma rvore vazia pode ser simplesmente:

Estruturas de Dados PUC-Rio

12-4

Arv* inicializa(void)
{
return NULL;
}

Para criar rvores no vazias, podemos ter uma operao que cria um n raiz dadas a
informao e suas duas sub-rvores, esquerda e direita. Essa funo tem como valor
de retorno o endereo do n raiz criado e pode ser dada por:
Arv* cria(char c, Arv* sae, Arv* sad){
Arv* p=(Arv*)malloc(sizeof(Arv));
p->info = c;
p->esq = sae;
p->dir = sad;
return p;
}

As duas funes inicializa e cria representam os dois casos da definio recursiva


de rvore binria: uma rvore binria (Arv* a;) vazia (a = inicializa();) ou
composta por uma raiz e duas sub-rvores (a = cria(c,sae,sad);). Assim, com
posse dessas duas funes, podemos criar rvores mais complexas.
Exemplo: Usando as operaes inicializa e cria, crie uma estrutura que represente
a rvore da Figura 13.5.
O exemplo da figura pode ser criada pela seguinte seqncia de atribuies.
Arv*
*/
Arv*
*/
Arv*
*/
Arv*
*/
Arv*
*/
Arv*
*/

a1= cria('d',inicializa(),inicializa());

/* sub-rvore com 'd'

a2= cria('b',inicializa(),a1);

/* sub-rvore com 'b'

a3= cria('e',inicializa(),inicializa());

/* sub-rvore com 'e'

a4= cria('f',inicializa(),inicializa());

/* sub-rvore com 'f'

a5= cria('c',a3,a4);

/* sub-rvore com 'c'

a = cria('a',a2,a5 );

/* rvore com raiz 'a'

Alternativamente, a rvore poderia ser criada com uma nica atribuio, seguindo a sua
estrutura, recursivamente:
Arv* a = cria('a',
cria('b',
inicializa(),
cria('d', inicializa(), inicializa())
),
cria('c',
cria('e', inicializa(), inicializa()),
cria('f', inicializa(), inicializa())
)
);

Para tratar a rvore vazia de forma diferente das outras, importante ter uma operao
que diz se uma rvore ou no vazia. Podemos ter:

Estruturas de Dados PUC-Rio

12-5

int vazia(Arv* a)
{
return a==NULL;
}

Uma outra funo muito til consiste em exibir o contedo da rvore. Essa funo deve
percorrer recursivamente a rvore, visitando todos os ns e imprimindo sua informao.
A implementao dessa funo usa a definio recursiva da rvore. Vimos que uma
rvore binria ou vazia ou composta pela raiz e por duas sub-rvores. Portanto, para
imprimir a informao de todos os ns da rvore, devemos primeiro testar se a rvore
vazia. Se no for, imprimimos a informao associada a raiz e chamamos
(recursivamente) a funo para imprimir os ns das sub-rvores.
void imprime (Arv* a)
{
if (!vazia(a)){
printf("%c ", a->info);
imprime(a->esq);
imprime(a->dir);
}
}

/* mostra raiz */
/* mostra sae */
/* mostra sad */

Exerccio: (a) simule a chamada da funo imprime aplicada arvore ilustrada pela
Figura 13.5 para verificar que o resultado da chamada a impresso de a b d c e f.
(b) Repita a experincia executando um programa que crie e mostre a rvore, usando o
seu compilador de C favorito.
Exerccio: Modifique a implementao de imprime, de forma que a sada impressa
reflita, alm do contedo de cada n, a estrutura da rvore, usando a notao introduzida
anteriormente.
Assim,
a
sada
da
funo
seria:
<a<b<><d<><>>><c<e<><>><f<><>>>>.
Uma outra operao que pode ser acrescentada a operao para liberar a memria
alocada pela estrutura da rvore. Novamente, usaremos uma implementao recursiva.
Um cuidado essencial a ser tomado que as sub-rvores devem ser liberadas antes de se
liberar o n raiz, para que o acesso s sub-rvores no seja perdido antes de sua
remoo. Neste caso, vamos optar por fazer com que a funo tenha como valor de
retorno a rvore atualizada, isto , uma rvore vazia, representada por NULL.
Arv* libera (Arv* a){
if (!vazia(a)){
libera(a->esq);
libera(a->dir);
free(a);
}
return NULL;
}

/* libera sae */
/* libera sad */
/* libera raiz */

Devemos notar que a definio de rvore, por ser recursiva, no faz distino entre
rvores e sub-rvores. Assim, cria pode ser usada para acrescentar (enxertar) uma
sub-rvore em um ramo de uma rvore, e libera pode ser usada para remover
(podar) uma sub-rvore qualquer de uma rvore dada.
Exemplo: Considerando a criao da rvore feita anteriormente:
Estruturas de Dados PUC-Rio

12-6

Arv* a = cria('a',
cria('b',
inicializa(),
cria('d', inicializa(), inicializa())
),
cria('c',
cria('e', inicializa(), inicializa()),
cria('f', inicializa(), inicializa())
)
);

Podemos acrescentar alguns ns, com:


a->esq->esq = cria('x',
cria('y',inicializa(),inicializa()),
cria('z',inicializa(),inicializa())
);

E podemos liberar alguns outros, com:


a->dir->esq = libera(a->dir->esq);

Deixamos como exerccio a verificao do resultado final dessas operaes.


importante observar que, anlogo ao que fizemos para a lista, o cdigo cliente que
chama a funo libera responsvel por atribuir o valor atualizado retornado pela
funo, no caso uma rvore vazia. No exemplo acima, se no tivssemos feito a
atribuio, o endereo armazenado em r->dir->esq seria o de uma rea de memria
no mais em uso.
Exerccio: Escreva uma funo que percorre uma rvore binria para determinar sua
altura. O prottipo da funo pode ser dado por:
int altura(Arv* a);

Uma outra funo que podemos considerar percorre a rvore buscando a ocorrncia de
um determinado caractere c em um de seus ns. Essa funo tem como retorno um
valor booleano (um ou zero) indicando a ocorrncia ou no do caractere na rvore.
int busca (Arv* a, char c){
if (vazia(a))
return 0;
/* rvore vazia: no encontrou */
else
return a->info==c || busca(a->esq,c) || busca(a->dir,c);
}

Note que esta forma de programar busca, em C, usando o operador lgico || (ou)
faz com que a busca seja interrompida assim que o elemento encontrado. Isto acontece
porque se c==a->info for verdadeiro, as duas outras expresses no chegam a ser
avaliadas. Analogamente, se o caractere for encontrado na sub-rvore da esquerda, a
busca no prossegue na sub-rvore da direita.
Podemos dizer que a expresso:
return c==a->info || busca(a->esq,c) || busca(a->dir,c);

equivalente a:

Estruturas de Dados PUC-Rio

12-7

if (c==a->info)
return 1;
else if (busca(a->esq,c))
return 1;
else
return busca(a->dir,c);

Finalmente, considerando que as funes discutidas e implementadas acima formam a


interface do tipo abstrato para representar uma rvore binria, um arquivo de interface
arvbin.h pode ser dado por:
typedef struct arv Arv;
Arv*
Arv*
int
void
Arv*
int

inicializa (void);
cria (char c, Arv* e, Arv* d);
vazia (Arv* a);
imprime (Arv* a);
libera (Arv* a);
busca (Arv* a, char c);

Ordens de percurso em rvores binrias


A programao da operao imprime, vista anteriormente, seguiu a ordem empregada
na definio de rvore binria para decidir a ordem em que as trs aes seriam
executadas:
Entretanto, dependendo da aplicao em vista, esta ordem poderia no ser a prefervel,
podendo ser utilizada uma ordem diferente desta, por exemplo:
imprime(a->esq);
imprime(a->dir);
printf("%c ", a->info);

/* mostra sae */
/* mostra sad */
/* mostra raiz */

Muitas operaes em rvores binrias envolvem o percurso de todas as sub-rvores,


executando alguma ao de tratamento em cada n, de forma que comum percorrer
uma rvore em uma das seguintes ordens:
pr-ordem: trata raiz, percorre sae, percorre sad;
ordem simtrica: percorre sae, trata raiz, percorre sad;
ps-ordem: percorre sae, percorre sad, trata raiz.
Para funo para liberar a rvore, por exemplo, tivemos que adotar a ps-ordem:
libera(a->esq);
libera(a->dir);
free(a);

/* libera sae */
/* libera sad */
/* libera raiz */

Na terceira parte do curso, quando tratarmos de rvores binrias de busca,


apresentaremos um exemplo de aplicao de rvores binrias em que a ordem de
percurso importante a ordem simtrica. Algumas outras ordens de percurso podem ser
definidas, mas a maioria das aplicaes envolve uma dessas trs ordens, percorrendo a
sae antes da sad.
Exerccio: Implemente verses diferentes da funo imprime, percorrendo a rvore em
ordem simtrica e em ps-ordem. Verifique o resultado da aplicao das duas funes
na rvore da Figura 13.5.
Estruturas de Dados PUC-Rio

12-8

13.2. rvores genricas


Nesta seo, vamos discutir as estruturas conhecidas como rvores genricas. Como
vimos, numa rvore binria o nmero de filhos dos ns limitado em no mximo dois.
No caso da rvore genrica, esta restrio no existe. Cada n pode ter um nmero
arbitrrio de filhos. Essa estrutura deve ser usada, por exemplo, para representar uma
rvore de diretrios.
Como veremos, as funes para manipularem uma rvore genrica tambm sero
implementadas de forma recursiva, e sero baseadas na seguinte definio: uma rvore
genrica composta por:
um n raiz; e
zero ou mais sub-rvores.
Estritamente, segundo essa definio, uma rvore no pode ser vazia, e a rvore vazia
no sequer mencionada na definio. Assim, uma folha de uma rvore no um n
com sub-rvores vazias, como no caso da rvore binria, mas um n com zero subrvores. Em qualquer definio recursiva deve haver uma condio de contorno, que
permita a definio de estruturas finitas, e, no nosso caso, a definio de uma rvore se
encerra nas folhas, que so identificadas como sendo ns com zero sub-rvores.
Como as funes que implementaremos nesta seo sero baseadas nessa definio, no
ser considerado o caso de rvores vazias. Esta pequena restrio simplifica as
implementaes recursivas e, em geral, no limita a utilizao da estrutura em
aplicaes reais. Uma rvore de diretrio, por exemplo, nunca vazia, pois sempre
existe o diretrio base o diretrio raiz.
Como as sub-rvores de um determinado n formam um conjunto linear e so dispostas
numa determinada ordem, faz sentido falarmos em primeira sub-rvore (sa1), segunda
sub-rvore (sa2), etc. Um exemplo de uma rvore genrica ilustrado na Figura 13.7.

Figura 13.7: Exemplo de rvore genrica.

Nesse exemplo, podemos notar que o a rvore com raiz no n a tem 3 sub-rvores, ou,
equivalentemente, o n a tem 3 filhos. Os ns b e g tem dois filhos cada um; os ns c e
i tem um filho cada, e os ns d, e, h e j so folhas, e tem zero filhos.

Estruturas de Dados PUC-Rio

12-9

De forma semelhante ao que foi feito no caso das rvores binrias, podemos representar
essas rvores atravs de notao textual, seguindo o padro: <raiz sa1 sa2 ...
san>. Com esta notao, a rvore da Figura 13.7 seria representada por:
a = <a <b <c <d>> <e>> <f> <g <h> <i <j>>>>

Podemos verificar que a representa a rvore do exemplo seguindo a seqncia de


definio a partir das folhas:
a1 = <d>
a2 = <c a1> = <c
a3 = <e>
a4 = <b a2 a3> =
a5 = <f>
a6 = <h>
a7 = <j>
a8 = <i a7> = <i
a9 = <g a6 a8> =
a = <a a4 a5 a9>

<d>>
<b <c <d>> <e>>

<j>>
<g <h> <i <j>>>
= <a <b <c <d>> <e>> <f> <g <h> <i <j>>>>

Representao em C
Dependendo da aplicao, podemos usar vrias estruturas para representar rvores,
levando em considerao o nmero de filhos que cada n pode apresentar. Se
soubermos, por exemplo, que numa aplicao o nmero mximo de filhos que um n
pode apresentar 3, podemos montar uma estrutura com 3 campos para apontadores
para os ns filhos, digamos, f1 , f2 e f3 . Os campos no utilizados podem ser
preenchidos com o valor nulo NULL, sendo sempre utilizados os campos em ordem.
Assim, se o n n tem 2 filhos, os campos f1 e f2 seriam utilizados, nessa ordem, para
apontar para eles, ficando f3 vazio. Prevendo um nmero mximo de filhos igual a 3, e
considerando a implementao de rvores para armazenar valores de caracteres simples,
a declarao do tipo que representa o n da rvore poderia ser:
struct arv3 {
char val;
struct no *f1, *f2, *f3;
};

A Figura 13.8 indica a representao da rvore da Figura 13.7 com esta organizao.
Como se pode ver no exemplo, em cada um dos ns que tem menos de trs filhos, o
espao correspondente aos filhos inexistentes desperdiado. Alm disso, se no existe
um limite superior no nmero de filhos, esta tcnica pode no ser aplicvel. O mesmo
acontece se existe um limite no nmero de ns, mas esse limite ser raramente
alcanado, pois estaramos tendo um grande desperdcio de espao de memria com os
campos no utilizados.

Estruturas de Dados PUC-Rio

12-10

Figura 13.8: rvore com no mximo trs filhos por n.

Uma soluo que leva a um aproveitamento melhor do espao utiliza uma lista de
filhos: um n aponta apenas para seu primeiro (prim) filho, e cada um de seus filhos,
exceto o ltimo, aponta para o prximo (prox) irmo. A declarao de um n pode ser:
struct arvgen {
char info;
struct arvgen *prim;
struct arvgen *prox;
};

A Figura 13.9 mostra o mesmo exemplo representado de acordo com esta estrutura.
Uma das vantagens dessa representao que podemos percorrer os filhos de um n de
forma sistemtica, de maneira anloga ao que fizemos para percorrer os ns de uma lista
simples.

Estruturas de Dados PUC-Rio

12-11

Figura 13.9: Exemplo usando lista de filhos.

Com o uso dessa representao, a generalizao da rvore apenas conceitual, pois,


concretamente, a rvore foi transformada em uma rvore binria, com filhos esquerdos
apontados por prim e direitos apontados por prox . Naturalmente, continuaremos a
fazer referncia aos ns nos termos da definio original. Por exemplo, os ns b, f e g
continuaro a ser considerados filhos do n a, como indicado na Figura 13.7, mesmo
que a representao usada na Figura 13.9 os coloque a distncias variveis do n pai.
Tipo abstrato de dado
Para exemplificar a implementao de funes que manipulam uma rvore genrica,
vamos considerar a criao de um tipo abstrato de dados para representar rvores onde a
informao associada a cada n um caractere simples. Nessa implementao, vamos
optar por armazenar os filhos de um n numa lista encadeada. Podemos definir o
seguinte conjunto de operaes:
cria: cria um n folha, dada a informao a ser armazenada;
insere: insere uma nova sub-rvore como filha de um dado n;
imprime: percorre todos os ns e imprime suas informaes;
busca: verifica a ocorrncia de um determinado valor num dos ns da rvore;
libera: libera toda a memria alocada pela rvore.
A interface do tipo pode ento ser definida no arquivo arvgen.h dado por:
typedef struct arvgen ArvGen;
ArvGen*
void
void
int
void

cria (char c);


insere (ArvGen* a, ArvGen* sa);
imprime (ArvGen* a);
busca (ArvGen* a, char c);
libera (ArvGen* a);

Estruturas de Dados PUC-Rio

12-12

A estrutura arvgen , que representa o n da rvore, definida conforme mostrado


anteriormente. A funo para criar uma folha deve alocar o n e inicializar seus campos,
atribuindo NULL para os campos prim e prox, pois trata-se de um n folha.
ArvGen* cria
{
ArvGen *a
a->info =
a->prim =
a->prox =
return a;
}

(char c)
=(ArvGen *) malloc(sizeof(ArvGen));
c;
NULL;
NULL;

A funo que insere uma nova sub-rvore como filha de um dado n muito simples.
Como no vamos atribuir nenhum significado especial para a posio de um n filho, a
operao de insero pode inserir a sub-rvore em qualquer posio. Neste caso, vamos
optar por inserir sempre no incio da lista que, como j vimos, a maneira mais simples
de inserir um novo elemento numa lista encadeada.
void insere (ArvGen* a, ArvGen* sa)
{
sa->prox = a->prim;
a->prim = sa;
}

Com essas duas funes, podemos construir a rvore do exemplo da Figura 13.7 com o
seguinte fragmento de cdigo:
/* cria ns como folhas */
ArvGen* a = cria('a');
ArvGen* b = cria('b');
ArvGen* c = cria('c');
ArvGen* d = cria('d');
ArvGen* e = cria('e');
ArvGen* f = cria('f');
ArvGen* g = cria('g');
ArvGen* h = cria('h');
ArvGen* i = cria('i');
ArvGen* j = cria('j');
/* monta a hierarquia */
insere(c,d);
insere(b,e);
insere(b,c);
insere(i,j);
insere(g,i);
insere(g,h);
insere(a,g);
insere(a,f);
insere(a,b);

Para imprimir as informaes associadas aos ns da rvore, temos duas opes para
percorrer a rvore: pr-ordem, primeiro a raiz e depois as sub-rvores, ou ps-ordem,
primeiro as sub-rvores e depois a raiz. Note que neste caso no faz sentido a ordem
simtrica, uma vez que o nmero de sub-rvores varivel. Para essa funo, vamos
optar por imprimir o contedo dos ns em pr-ordem:
void imprime (ArvGen* a)
{
ArvGen* p;
printf("%c\n",a->info);
for (p=a->prim; p!=NULL; p=p->prox)
imprime(p);
}
Estruturas de Dados PUC-Rio

12-13

A operao para buscar a ocorrncia de uma dada informao na rvore exemplificada


abaixo:
int busca (ArvGen* a, char c)
{
ArvGen* p;
if (a->info==c)
return 1;
else {
for (p=a->prim; p!=NULL; p=p->prox) {
if (busca(p,c))
return 1;
}
}
return 0;
}

A ltima operao apresentada a que libera a memria alocada pela rvore. O nico
cuidado que precisamos tomar na programao dessa funo a de liberar as subrvores antes de liberar o espao associado a um n (isto , usar ps-ordem).
void libera (ArvGen* a)
{
ArvGen* p = a->prim;
while (p!=NULL) {
ArvGen* t = p->prox;
libera(p);
p = t;
}
free(a);
}

Exerccio: Escreva uma funo com o prottipo


ArvGen* copia(ArvGen*a);

para criar dinamicamente uma cpia da rvore.


Exerccio: Escreva uma funo com o prottipo
int igual(ArvGen*a, ArvGen*b);

para testar se duas rvores so iguais.

Estruturas de Dados PUC-Rio

12-14

Você também pode gostar