Você está na página 1de 44

Estruturas de Dados Aula 15: rvores

17/05/2011

Fontes Bibliogrficas
Livros:
Introduo a Estruturas de Dados (Celes, Cerqueira e Rangel): Captulo 13; Projeto de Algoritmos (Nivio Ziviani): Captulo 5; Estruturas de Dados e seus Algoritmos (Szwarefiter, et. al): Captulo 3; Algorithms in C (Sedgewick): Captulo 5;

Slides baseados no material da PUC-Rio, disponvel em http://www.inf.pucrio.br/~inf1620/.

Introduo
Estruturas estudadas at agora no so adequadas para representar dados que devem ser dispostos de maneira hierrquica
Ex., hierarquia de pastas rvore genealgica

rvores so estruturas adequadas para representao de hierarquias

Definio Recursiva de rvore


Um conjunto de ns tal que:
existe um n r, denominado raiz, com zero ou mais subrvores, cujas razes esto ligadas a r os ns razes destas sub-rvores so os filhos de r os ns internos da rvore so os ns com filhos as folhas ou ns externos da rvore so os ns sem filhos

Formas de representao
Representao por parnteses aninhados
( A (B) ( C (D (G) (H)) (E) (F (I))))

Diagrama de Incluso

Representao Hierrquica

Subrvore

Seja a rvore acima T = {A, B, ...} A rvore T possui duas subrvores:


Tb e Tc onde Tb = { B } e Tc = {C, D, ...}

A subrvore Tc possui 3 subrvores:


Td, Tf e Te onde Td = {D, G, H}, Tf = {F, I}, Te = {E}

As subrvores Tb, Te, Tg, Th, Ti possuem apenas o n raiz e nenhuma subrvore.

Exemplo (rvore de expresso)


Representao da expresso aritmtica:
(a + (b * (c / d - e)))

Conceitos Bsicos
Ns filhos, pais, tios, irmos e av Grau de sada (nmero de filhos de um n) N folha (grau de sada nulo) e n interior (grau de sada diferente de nulo) Grau de uma rvore (mximo grau de sada) Floresta (conjunto de zero ou mais rvores)

Conceitos Bsicos (2)


Caminho
Uma sequncia de ns distintos v1, v2, ..., vk, tal que existe sempre entre ns consecutivos (isto , entre v1 e v2, entre v2 e v3, ... , v(k-1) e vk) a relao " filho de ou " pai de" denominada um caminho na rvore.

Comprimento do Caminho
Um caminho de vk vrtices obtido pela sequncia de k-1 pares. O valor k-1 o comprimento do caminho.

Nvel ou profundidade de um n
nmero de ns do caminho da raiz at o n.

Conceitos Bsicos (3)


Nvel da raiz (profundidade) 0. rvore Ordenada: aquela na qual filhos de cada n esto ordenados. Assume-se ordenao da esquerda para a direita. Esta rvore ordenada?

Conceitos Bsicos (4)


rvore Cheia: Uma rvore de grau d uma rvore cheia se possui o nmero mximo de ns, isto , todos os ns tm nmero mximo de filhos exceto as folhas, e todas as folhas esto na mesma altura. rvore cheia de grau 2: implementao sequencial.

Armazenamento por nvel: posio do n 1 2 3 i posio dos filhos do n 2,3 4,5 6,7 (2i,2i+1)

Exemplo
rvore binria representando expresses aritmticas binrias
Ns folhas representam os operandos Ns internos representam os operadores (3+6)*(4-1)+5

rvores Binrias
Notao textual
a rvore vazia representada por <> rvores no vazias por <raiz sae sad>

Exemplo:
<a <b <> <d<><>> > <c <e<><>> <f<><>>> >

rvore Binria
Uma rvore em que cada n tem zero, um ou dois filhos Uma rvore binria :
uma rvore vazia; ou um n raiz com duas sub-rvores:
a subrvore da direita (sad) a subrvore da esquerda (sae)

rvores Binrias Implementao em C


Representao: ponteiro para o n raiz Representao de um n na rvore:
Estrutura em C contendo
A informao propriamente dita (exemplo: um caractere, ou inteiro) Dois ponteiros para as sub-rvores, esquerda e direita

struct arv { char info; struct arv* esq; struct arv* dir; };

TAD rvores Binrias Impl. em C (arv.h)


typedef struct arv Arv; //Cria uma rvore vazia Arv* arv_criavazia (void); //cria uma rvore com a informao do n raiz c, e //com subrvore esquerda e e subrvore direita d Arv* arv_cria (char c, Arv* e, Arv* d); //libera o espao de memria ocupado pela rvore a Arv* arv_libera (Arv* a); //retorna true se a rvore estiver vazia e false //caso contrrio int arv_vazia (Arv* a); //indica a ocorrncia (1) ou no (0) do caracter c int arv_pertence (Arv* a, char c); //imprime as informaes dos ns da rvore void arv_imprime (Arv* a);

TAD rvores Binrias Implementao em C


Implementao das funes:
implementao em geral recursiva usa a definio recursiva da estrutura

Uma rvore binria :


uma rvore vazia; ou um n raiz com duas sub-rvores:
a sub-rvore da direita (sad) a sub-rvore da esquerda (sae)

TAD rvores Binrias Implementao em C


funo arv_criavazia
cria uma rvore vazia

Arv* arv_criavazia (void){ return NULL; }

TAD rvores Binrias Implementao em C


funo arv_cria
cria um n raiz dadas a informao e as duas sub-rvores, a da esquerda e a da direita retorna o endereo do n raiz criado

Arv* 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; }

TAD rvores Binrias Implementao em C

arv_criavazia e arv_cria
as duas funes para a criao de rvores representam os dois casos da definio recursiva de rvore binria:
uma rvore binria Arv* a;
vazia a=arv_criavazia() composta por uma raiz e duas sub-rvores a=arv_cria(c,sae,sad);

TAD rvores Binrias Implementao em C


funo arv_vazia
indica se uma rvore ou no vazia

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

TAD rvores Binrias Implementao em C


funo arv_libera
libera memria alocada pela estrutura da rvore
as sub-rvores devem ser liberadas antes de se liberar o n raiz

retorna uma rvore vazia, representada por NULL

Arv* arv_libera (Arv* a){ if (!arv_vazia(a)){ arv_libera(a->esq); /* libera sae */ arv_libera(a->dir); /* libera sad */ free(a); /* libera raiz */ } return NULL; }

TAD rvores Binrias Implementao em C


funo arv_pertence
verifica a ocorrncia de um caractere c em um dos ns retorna um valor booleano (1 ou 0) indicando a ocorrncia ou no do caractere na rvore

int arv_pertence (Arv* a, char c){ if (arv_vazia(a)) return 0; /* rvore vazia: no encontrou */ else return a->info==c || arv_pertence(a->esq,c) || arv_pertence(a->dir,c); }

TAD rvores Binrias Implementao em C


funo arv_imprime
percorre recursivamente a rvore, visitando todos os ns e imprimindo sua informao

void arv_imprime (Arv* a){ if (!arv_vazia(a)){ printf("%c ", a->info); /* mostra raiz */ arv_imprime(a->esq); /* mostra sae */ arv_imprime(a->dir); /* mostra sad */ } }

Exemplo
Criar a rvore <a <b <> <d <><>> > <c <e <><> > <f <><> > > >
/* sub-rvore 'd' */ Arv* a1= arv_cria('d',arv_criavazia(),arv_criavazia()); /* sub-rvore 'b' */ Arv* a2= arv_cria('b',arv_criavazia(),a1); /* sub-rvore 'e' */ Arv* a3= arv_cria('e',arv_criavazia(),arv_criavazia()); /* sub-rvore 'f' */ Arv* a4= arv_cria('f',arv_criavazia(),arv_criavazia()); /* sub-rvore 'c' */ a Arv* a5= arv_cria('c',a3,a4); /* rvore 'a' */ b c Arv* a = arv_cria('a',a2,a5 );
d e f

Exemplo
Criar a rvore <a <b <> <d <><>> > <c <e <><> > <f <><> > > >
Arv* a = arv_cria(a, arv_cria(b, arv_criavazia(), arv_cria(d, arv_criavazia(), arv_criavazia()) ), arv_cria(c, arv_cria(e, arv_criavazia(), arv_criavazia()), arv_cria(f, arv_criavazia(), arv_criavazia()) ) a );
b d e c f

Exemplo
Acrescenta ns x, y e z a->esq->esq = arv_cria(x, arv_cria(y, arv_criavazia(), arv_criavazia()), arv_cria(z, arv_criavazia(), arv_criavazia()) );
y

a b x z d e c f

Exemplo
Libera ns a->dir->esq = arv_libera(a->dir->esq);

a b x y z d e c f

Ordem de Percurso (ou travessia) rvores Binrias


Pr-ordem:
trata raiz, percorre sae, percorre sad exemplo: a b d c e f
a

Ordem simtrica (ou In-Ordem):


percorre sae, trata raiz, percorre sad exemplo: b d a e c f

Ps-ordem:
percorre sae, percorre sad, trata raiz exemplo: d b e f c a

Ordem de Percurso - Exerccios


Fazer percurso de Pr-ordem In-ordem Ps-ordem

Pre-ordem
+*+36-415

In-ordem
3+6*4-1+5

Ps-ordem
36+41-*5+

Pr-Ordem Implementao recursiva


void arv_preordem (Arv* a) { if (!arv_vazia(a)) { processa(a); // por exemplo imprime arv_preordem(a->esq); arv_preordem(a->dir); } }

In-Ordem Implementao recursiva


void arv_inordem (Arv* a) { if (!arv_vazia(a)) { arv_inordem (a->esq); processa (a); // por exemplo imprime arv_inordem (a->dir); } }

Ps-Ordem Implementao recursiva


void arv_posordem (Arv* a) { if (!arv_vazia(a)) { arv_posordem (a->esq); arv_posordem (a->dir); processa (a); // por exemplo imprime } }

Pergunta
funo arv_pertence
Pr-ordem, ps-ordem ou in-ordem?

int arv_pertence (Arv* a, char c) { if (arv_vazia(a)) return 0; /* rvore vazia: no encontrou */ else return a->info==c || arv_pertence(a->esq,c) || arv_pertence(a->dir,c); }

Pergunta
funo arv_libera
Pr-ordem, ps-ordem ou in-ordem?

Arv* arv_libera (Arv* a){ if (!arv_vazia(a)){ arv_libera(a->esq); /* libera sae */ arv_libera(a->dir); /* libera sad */ free(a); /* libera raiz */ } return NULL; }

rvores Binrias - Altura


Propriedade das rvores
Existe apenas um caminho da raiz para qualquer n

Altura de uma rvore


comprimento do caminho mais longo da raiz at uma das folhas a altura de uma rvore com um nico n raiz zero a altura de uma rvore vazia -1

Esforo computacional necessrio para alcanar qualquer n da rvore proporcional altura da rvore Exemplo: a
h=2
b c

rvores Binrias - conceitos


Nvel de um n
a raiz est no nvel 0, seus filhos diretos no nvel 1, ... o ltimo nvel da rvore a altura da rvore

nvel 0

nvel 1

nvel 2

rvores Binrias - conceitos


rvore Cheia
todos os seus ns internos tm duas sub-rvores associadas nmero n de ns de uma rvore cheia de altura h n = 2h+1 -1

rvores Binrias - conceitos


rvore Degenerada
Ns internos tm uma nica subrvore associada Vira uma estrutura linear Arvore de altura h tem n = h+1

Altura de uma rvore


Importante medida de eficincia (visitao do n) rvore com n ns: Altura mnima proporcional a log n (rvore binria cheia) Altura mxima proporcional a n (rvore degenerada)

Exerccios
Escrever uma funo recursiva que calcule a altura de uma rvore binria dada. A altura de uma rvore igual ao mximo nvel de seus ns.

Respostas
static int max2 (int a, int b) { return (a > b) ? a : b; }

int arv_altura (Arv* a) { if (arv_vazia(a)) return -1; else return 1 + max2 (arv_altura (a->esq), arv_altura (a->dir)); }

Exerccios
Escrever o algoritmo de visita em Pr-Ordem utilizando alocao dinmica mas sem utilizar procedimentos recursivos. Utilizar pilha (definindo um vetor que pode ser acessado pelo topo) para saber o endereo da subrvore que resta direita.
processar raiz A guardar A na pilha para poder acessar C depois passa B e processa essa subrvore idem para D retorna B (topo da pilha) para acessar D que a subrvore esquerda

Respostas
void arv_preordem (Arv* a) { Arv* A[MAX]; //qual seria o valor de max? Arv* p; Arv* raiz; int topo; int acabou; topo = 0; p = a; acabou = arv_vazia(a); //inicializaes while (!acabou) // enquanto houver ns para processar { while (!arv_vazia(p)) { processa (p->info); topo++; A[topo] = p; p = p->esq; } if (topo != 0) { p = A[topo]->dir; topo--; } else {acabou = 1;} } }

Para casa
Fazer funo para retornar o pai de um dado n de uma rvore
Dado um item, procura se item existe na rvore (usando algum algoritmo de travessia) Caso positivo retorna o contedo do pai do n Pode ser recursivo ou no

Você também pode gostar