1. Introduo
2. Definies Bsicas
3. rvores Binrias
4. Armazenamento de rvores Binrias
5. Uma Aplicao de rvores Binrias
6. Percorrendo rvores Binrias
7. O Algoritmo de Huffman
8. Removendo Ns de rvores Binrias
9. rvores Binrias Balanceadas
10. Exerccios
Introduo
Definies Bsicas
rvores so estruturas de dados extremamente teis em muitas aplicaes. Uma rvore
formada por um conjunto finito T de elementos denominados vrtices ou ns de tal
modo que se T = 0 a rvore vazia, caso contrrio temos um n especial chamado raiz
da rvore (r), e cujos elementos restantes so particionados em m>=1 conjuntos
distintos no vazios, as subrvores de r, sendo cada um destes conjuntos por sua vez
uma rvore.
A forma convencional de representar uma rvore est indicado na figura aini abaixo.
Esta rvore tem nove ns sendo A o n raiz.
Os conjuntos das subrvores tem de ser disjuntos tem de ser disjuntos portanto a
estrutura indicada na Figura arvn no uma rvore.
nvel 0 = A
nvel 1 = B, C
nvel 2 = D, E, F, G
nvel 3 = H, I
Uma outra notao que encontramos a toda hora, e que est representada na figura
arviden, a forma identada ou de diagrama de barras. Notar que esta representao
lembra um sumrio de livro. Os sumrios dos livros so representaes da rvore do
contedo do livro.
(A (B(D))(C(E(H)(I))(F)(G)))
Esta representao tem importncia, por exemplo, no tratamento de expresses
aritmticas, j que toda expresso aritmtica pode ser colocada nesta forma. Se
colocarmos uma expresso nesta forma podemos ento represent-la como uma rvore,
mostrando como ela seria calculada. Para colocarmos uma expresso em forma de
rvore devemos considerar cada operador como um n da rvore e os seus operandos
como as duas subrvores. Considere a expresso C seguinte
A + (B-C)*D%(E*F)
que aps receber todos os parnteses fica da seguinte maneira
(A + ((B-C)*(D%(E*F))))
A figura arvexp mostra como fica esta expresso representada por uma rvore.
rvores Binrias
A figura arvbin abaixo mostra um importante tipo de rvore que a rvore binria. Em
uma rvore binria cada n tem no mximo duas subrvores, e quando h somente uma
presente necessrio distinguir entre subrvore esquerda e direita. rvores binrias
podem ser vistas em diversas situaes do cotidiano. Por exemplo, um torneio de
futebol eliminatrio, do tipo das copas dos pases, como a Copa do Brasil, em que a
cada etapa os times so agrupados dois a dois e sempre so eliminados metade dos
times uma rvore binria.
Uma rvore estritamente binria uma rvore binria em que cada n tem 0 ou 2 filhos.
Uma rvore binria cheia uma rvore em que se um n tem alguma sub-rvore vazia
ento ele est no ltimo nvel. Uma rvore completa aquela em se n um n com
algumas de subrvores vazias, ento n se localiza no penltimo ou no ltimo nvel.
Portanto, toda rvore cheia completa e estritamente binria. A Figura arvbcc mostra
uma rvore estritamente binria, completa e cheia.
pos_esq aceita um ponteiro p para uma rvore binria sem filho esquerdo e cria um
novo filho esquerdo contendo a informao x. Um possvel algoritmo para esta funo
pode ser:
if (p->left)
puts("Operao ilegal");
else {
q = cria_arvore();
p->left = q;
}
O algoritmo pos_dir semelhante a este com a diferena que ele cria um n a direita.
#include<stdlib.h>
#include<string.h>
typedef struct stNo {
int info;
struct stNo *esq, *dir;
} tNo ;
tNo *cria_arvore( int );
tNo *cria_no( );
void pos_esq (tNo *, int );
void pos_dir (tNo *, int );
void main() {
tNo *raiz, *p, *q;
char linha[80], *numero;
int num;
gets(linha);
numero = strtok(linha, " "); /* pega o primeiro numero da lista */
num = atoi(numero);
raiz = cria_arvore(num); /* insere na raiz */
numero = strtok(NULL, " ");
while (numero) {
q = raiz; p = raiz;
printf("Li numero %d\n", num); /* le novo numero */
num = atoi(numero);
while (num != p->info && q) { /* procura na arvore */
p = q;
if (num < p->info)
q = p->esq;
/* passa para arvore esquerda */
else
q = p->dir;
/* passa para direita */
}
if (num == p->info)
printf("O numero %d ja existe na arvore.\n", num);
else { /* vou inserir o numero na arvore */
if (num < p->info)
pos_esq(p, num);
else
pos_dir(p, num);
}
numero = strtok(NULL, " ");
} /* fim do while (numero) */
p = cria_no ();
if (p) {
p->info = x;
return p;
}
else {
puts("Faltou espaco para alocar no.");
exit(1);
}
tNo *cria_no() {
tNo *p;
if ((p =
return
else {
p->esq
return
}
if (p->dir)
puts("Operacao de insercao a direita ilegal.");
else {
q = cria_arvore(x);
p->dir = q;
}
Um algoritmo recursivo para implementar este modo de percurso pode ser o seguinte:
void em_ordem ( tipoNo *pt) {
if (pt) {
em_ordem (pt->esq);
visita (pt);
em_ordem (pt->dir);
}
}
O percurso em ps-ordem pode ser aplicado no clculo da altura de uma rvore. Para
calcular a altura de uma rvore necessrio calcular o maior caminho da raiz at uma de
suas folhas. Deste modo s podemos calcular o comprimento de um caminho a partir de
um n v aps percorrermos todos os seus descendentes. O algoritmo mostrado abaixo
mostra como fica a implementao da funo visita para que ela calcule a altura do
n.
void visita (tNo *p) {
int alt1, alt2;
if (p->esq) alt1 = p->esq->altura;
else alt1 = 0;
if (p->dir) alt2 = p->dir->altura;
else alt2 = 0;
if (alt1>alt2)
else p->altura
printf("info =
printf("altura
p->altura = alt1 + 1;
= alt2 + 1;
%d ", p->info);
= %d\n", p->altura);
Algoritmo de Huffman
Para analisarmos mais uma aplicao de rvores binrias vamos considerar o problema
de codificar uma mensagem composta de uma seqncia de smbolos de um alfabeto de
n smbolos. Esta mensagem ser transformada em uma seqncia de bits, depois de a
cada smbolo for atribudo um cdigo binrio e os cdigos dos smbolos da mensagem
forem concatenados.
Considere um alfabeto composto de quatro smbolos A, B, C e D, sendo que a cada um
dos smbolos foi atribudo o cdigo indicado a seguir:
Smbolo
Cdigo
00
01
10
11
Smbolo
Freqncia
Desta tabela podemos verificar que se atribuirmos ao smbolo A um cdigo binrio mais
curto que os atribudos aos smbolos B e D teramos uma mensagem menor. Isto provm
do fato que o smbolo A aparece mais vezes do que os smbolos B e D. Suponha que os
seguintes cdigos sejam atribudos aos smbolos
Smbolo
Cdigo
110
10
111
O texto abaixo mosta uma rotina que remove ns de uma rvore, que contm nmeros
inteiros. O programa completo est em arvremov.c.
tNo *remover (tNo *tree, int num) {
tNo *p, /* p aponta para o no a ser removido */
*q, /* q aponta para o pai do no */
*rp, /* rp aponta que ira substituir o no p */
*f,
*s; /* sucessor do no p */
p = tree; q=NULL;
/* procura o no com a chave num, p aponta para o no
e q aponta para o pai do no */
while ( p && p->info != num) {
q = p;
if ( num < p->info)
p = p->esq;
else
p = p->dir;
} /* fim do while */
if (!p) return NULL; /* a chave nao existe na arvore */
Observemos uma subrvore que ser tornar desbalanceada quando ocorrer uma
insero. Vamos supor tambm que este n tem um balanceamento de 1. Neste caso o
desbalanceamento ocorrer se a insero ocorrer em um n da direita. A Figura arvins
mostra um exemplo deste caso.
q->esquerda = p;
p->direita = temp;
Para verificar o que fazer em uma rvore T aps a insero de um n q vamos
considerar os vrios casos possveis. Primeiro, se aps a incluso todos os ns se
mantiveram regulados, ento a rvore se manteve AVL e nada h a fazer. Caso contrrio
vamos considerar o n p mais prximo das folhas, que se tornou desregulado. A escolha
de p nica, pois qualquer subrvore de T que se tornou desregulada deve incluir p.
Sejam hd(p) e he(p) as alturas direita e esquerda das subrvores de p, portanto
|hd(p) - he(p)| = 2
pois T era AVL.
Temos os seguintes casos:
caso 1: hd(p) >he(p)
neste caso q pertence a subrvore esquerda de p. Alm disso p possui o filho esquerdo u
<> q, seno p no estaria desregulado. Sabe-se tambm que hd(u) <>he(u), pela mesma
razo. Para o caso 1 temos duas possibilidades:
caso 1.1
Exerccios
1. Escreva um programa que crie uma rvore de busca binria a partir de letras
lidas do teclado. O programa deve imprimir a rvore nos trs modos de percurso.
Soluo: arv0301.c
2. Faa uma funo que imprima os ns de uma rvore na sequencia de seus nveis.
Soluo: niveis.c
3. Escreva um programa que leia um arquivo que contem varios numeros inteiros
(cada numero em uma linha) e imprima os numeros em ordem crescente (utilize
uma arvore para armazenar os numeros na memoria.
Soluo: ordem.c
Este arquivo encontra-se em http://equipe.nce.ufrj.br/adriano/c/apostila/arvore.htm