You are on page 1of 34

Em Construo, com vi!!!

Data da ltima atualizao: 13/03/2000


copyright Adriano Cruz 1999

rvores
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.

Figura (aini): Uma rvore

Os conjuntos das subrvores tem de ser disjuntos tem de ser disjuntos


portanto a estrutura indicada na Figura arvn no uma rvore.
Figura arvn: Estrutura que no representa uma rvore

Se n um n da rvore T ento Tn indica uma subrvore de T com raiz no


n n. Os ns n1, n2, ..., nk das subrvores de Tn so chamados de filhos de n
e n o pai destes ns, que so ns irmos. Os ns B e C so filhos de A e
ns irmos. Ns sem filhos como os ns D, H, I, F e G so chamados de
folhas. A subrvore da esquerda do n A tem raiz em B e a subrvore da
direita tem raiz em C, isto est indicado pelos dois ramos saindo de A. A
ausncia de um ramo na rvore indica uma subrvore vazia, como a
subrvore da direita do n B. O nmero de de filhos de um n chamado
de grau de sada deste n. Por exemplo, o n C tem grau de sada 3 e o n
E grau 2. Se o n n a raiz de uma subrvore Tn e n1 pertence a Tn ento n1
descendente de n e n ancestral de n1. Portanto ns sem descendentes
prprios uma folha. Por exemplo, o n H ancestral do n C e o n D
descendente do n A.
Um caminho da rvore composto por uma seqncia de ns consecutivos
(n1, n2, ..., nk-1, nk) tal que existe sempre a relao ni pai de ni+1. Os k
vrtices formam k-1 pares e um caminho de comprimento igual a k-1. O
comprimento do caminho entre o n A e o n H 3.

O nvel de um n n pode ser definido do seguinte modo: o n raiz tem


nvel 0, os outros ns tem um nvel que maior uma unidade que o nvel
de seu pai. Na rvore da figura anterior temos ns nos seguintes nveis:

nvel 0 = A
nvel 1 = B, C
nvel 2 = D, E, F, G
nvel 3 = H, I

A altura de um n n o nmero de ns do maior caminho de n at um de


seus descendentes. As folhas tem altura 1.

Existem diversas maneiras de representar rvores. Uma representao que


reflete a idia de rvores como conjuntos aninhados mostrado na figura
arvconj abaixo. A figura mostra o mesmo conjunto da figura aini.

Figura (arconj): rvore representada como conjuntos aninhados.


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.

Figura (arviden) rvore e sua representao por barras

Uma outra forma interessante de representar uma rvore a representao


por parnteses aninhados. Da mesma forma que a figura aini representa
uma rvore no plano a representao por parnteses representa uma rvore
em uma linha. A seqncia de parnteses representa a relao entre os ns
da estrutura. O rtulo do n inserido esquerda do abre parnteses
correspondente. A rvore representada planarmente pela figura aini pode
ser representada em uma linha por

(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.

Figura (arvexp) Uma expresso e sua representao como 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.
Figura abin: rvore binria

Formalmente uma rvore binria pode ser definida como um conjunto


finito de ns, que vazio, ou consiste de um n raiz e dois conjuntos
disjuntos de ns, a subrvore esquerda e a subrvore direita. importante
observar que uma rvore binria no um caso especial de rvore e sim
um conceito completamente diferente. Por exemplo, considere a figura
arvbind, note que so duas rvores idnticas, mas so duas rvores binrias
diferentes. Isto porque uma delas tem a subrvore da direita vazia e a outra
a subrvore da esquerda.
Figura arcbind: rvores binrias diferentes.

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.

Armazenamento de rvores Binrias


Para armazenar cada n de uma rvore binria precisamos de uma
estrutura que contenha dois ponteiros: um aponta para a subrvore
esquerda e outro para a subrvore direita. Naturalmente, devemos ter o(s)
campo(s) para armazenar as informaes que o n deve conter. Nos
algoritmos que iremos mostrar consideraremos que existe a seguinte
definio para a estrutura do n:
typedef struct sttNo {
tipo inf;
struct sttNo *esq, *dir;
} tNo;

A Figura armarv mostra um diagrama de como seria o armazenamento de


uma rvore binria. Observar que se desconsiderarmos os campos de
informao para armazenar uma rvore com n ns precisamos de 2n+1
unidades de memria.
No processo de criar uma rvore precisaremos de trs operaes
importantes: cria_arvore, pos_esq e pos_dir. cria_arvore
cria uma rvore binria nova consistindo de um nico n, armazena a
informao. e retorna um ponteiro para este n. Um algoritmo para esta
funo pode ser o seguinte:

p = cria_no();
p->info = x;
p->esq = NULL;
p->dir = NULL;
return p;

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.

Uma Aplicao de rvores Binrias


As rvore binrias so estruturas importantes toda vez que uma deciso
binria deve ser tomada em algum ponto de um algoritmo. Vamos agora,
antes de passar a algoritmos mais complexos, mostrar uma aplicao
simples de rvores binrias. Suponhamos que precisamos descobrir
nmeros duplicados em uma lista no ordenada de nmeros. Uma maneira
comparar cada novo nmero com todos os nmeros j lidos. Isto
aumenta em muito a complexidade do algoritmo. Outra possibilidade
manter uma lista ordenada dos nmeros e a cada nmero lido fazer uma
busca na lista. Outra soluo usar uma rvore binria para manter os
nmeros. O primeiro nmero lido colocado na raiz da rvore. Cada novo
nmero lido comparado com o elemento raiz, caso seja igual uma
duplicata e voltamos a ler outro nmero. Se menor repetimos o processo
com a rvore da direita e se maior com a rvore da esquerda. Este processo
continua at que uma duplicata encontrada ou uma rvore vazia
achada. Neste caso, o nmero inserido na posio devida na rvore.
Considere que os nmeros
7 8 2 5 8 3 5 10 4

foram fornecidos pelo usurio, neste caso a rvore binria mostrada na


Figura arbus seria construida.
O programa arv0300.c mostra este algoritmo. O programa insere os ns na
rvore e imprime uma mensagem caso seja fornecido um nmero que j
foi lido antes.

/* programa arv0300.c */
#include<stdio.h>
#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) */
}
tNo *cria_arvore (int x) {
tNo *p;

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 = (tNo *) malloc(sizeof(tNo))) == NULL)


return NULL;
else {
p->esq = NULL; p->dir = NULL;
return p;
}
}

void pos_esq(tNo *p, int x) {


tNo *q;

if (p->esq)
puts("Operacao de insercao a esquerda ilegal.");
else {
q = cria_arvore(x);
p->esq = q;
}
}

void pos_dir(tNo *p, int x) {


tNo *q;
if (p->dir)
puts("Operacao de insercao a direita ilegal.");
else {
q = cria_arvore(x);
p->dir = q;
}
}

Percorrendo rvores Binrias


Uma operao muito comum percorrer uma rvore binria, o que
significa passar por todos os ns, pelo menos uma vez. O conceito de
visitar significa executar uma operao com a informao armazenada no
n, por exemplo, imprimir seu contedo. Na operao de percorrer a
rvore pode-se passar por alguns ns mais de uma vez, sem porm visit-
los.
Uma rvore uma estrutura no seqncial, diferentemente de uma lista,
por exemplo. No existe ordem natural para percorrer rvores e portanto
podemos escolher diferentes maneiras de percorr-las. Ns iremos estudar
trs mtodos para percorrer rvores. Todos estes trs mtodos podem ser
definidos recursivamente e se baseiam em trs operaes bsicas: visitar a
raiz, percorrer a subrvore da esquerda e percorrer a subrvore da direita.
A nica diferena entre estes mtodos a ordem em que estas operaes
so executadas.
O primeiro mtodo, conhecido como percurso em pr-ordem, implica em
executar recursivamente os trs passos na seguinte ordem.

1. Visitar a raiz;
2. Percorrer a subrvore da esquerda em pr-ordem;
3. Percorre a subrvore da direita em pr-ordem.
Para a rvore da Figura arvbinp este percurso forneceria, no caso da visita
significar imprimir, os seguintes resultados: F B A D C E H G I. Uma
aplicao interessante deste tipo de percurso aplic-lo uma rvore que
contenha uma expresso aritmtica, a qual foi expandida e recebeu todos
os parnteses. Por exemplo, aplicando-se o percurso em pr-ordem
rvore arvexp obtm-se como resultado a expresso em notao polonesa
normal, isto os operandos antes dos operadores. Deste modo o resultado
+A*-BC%D*EF. Observar que esta notao diferente da notao
polonesa reversa, em que os operadores aparecem depois dos operandos.
Um algoritmo recursivo para implementar este modo de percurso pode ser
o seguinte:
void pre_ordem ( tipoNo *pt) {
if (pt) {
visita (pt);
pre_ordem (pt->esq);
pre_ordem (pt->dir);
}
}

Para percorrer a rvore em ordem simtrica executa-se recursivamente os


trs passos na seguinte ordem:

1. Percorrer a subrvore da esquerda em ordem simtrica;


2. Visitar a raiz;
3. Percorrer a subrvore da direita em ordem simtrica.
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);
}
}

Para a rvore da Figura arvbin o percurso forneceria o seguinte resultado


A B C D E F G H I.

Este tipo de percurso muito empregado em rvores binrias de busca.


Considere a rvore mostrada na Figura arvbus, que foi gerada como est
indicado na seo Uma Aplicao de rvores Binrias. Caso a rvore seja
percorrida em ordem simtrica o resultado seria

2 3 4 5 7 8 10

que so os nmeros lidos em ordem crescente sem repetio.

O percurso conhecido como ps-ordem feito a partir dos trs passos na


seguinte ordem:

1. Percorrer a subrvore da esquerda em ps-ordem;


2. Percorrer a subrvore da direita em ps-ordem;
3. Visitar a raiz;
Para a rvore da Figura arvbin o percurso forneceria o seguinte resultado
A C E D B G I H F. Um algoritmo recursivo para implementar este
percurso poderia ser:
void pos_ordem(tipoNo *pt) {
if (pt) {
pos_ordem(pt->esq);
pos_ordem(pt->dir);
visita(pt);
}
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) p->altura = alt1 + 1;
else p->altura = alt2 + 1;
printf("info = %d ", p->info);
printf("altura = %d\n", p->altura);
}

As variveis alt1 e alt2 armazenam a altura das subrvores da esquerda e


da direita e o campo altura um novo campo da estrutura que armazena
o n. A altura de um n igual ao maior valor entre as alturas esquerda e
direita incrementado de um.

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
A 0
B 1
C 10
D 11

A mensagem ABCADCA seria codificada da seguinte maneira
00011000111000, tendo comprimento de 14 bits. O objetivo do algoritmo
criar um cdigo que minimize o comprimento da mensagem. Para criar
este cdigo vamos levar em conta a freqncia de cada smbolo na
mensagem. A Tabela a seguir mostra a freqncia de cada smbolo na
mensagem

Smbolo Freqncia
A 3
B 1
C 2
D 1
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
A 0
B 110
C 10
D 111
Usando estge cdigo a mensagem ABCADCA ficaria 0110100111100 que
requer 13 bits. Em mensagens longas com mais smbolos infrequentes o
ganho pode ser maior. Um dos requerimentos deste cdigo que nenhum
cdigo seja prefixo de outro, caso a decodificao seja feita da esquerda
para direita.

Para decodificar a mensagem vamos comear da esquerda para a direita,


caso o primeiro bit seja 0 o cdigo corresponde ao smbolo A. No caso
contrrio devemos continuar a examinar os bits restantes. Se o segundo bit
for 0 o smbolo um C, caso contrrio examinamos o terceiro bit, um 0
indica um B e D no outro caso.

Do que vomos at agora o algoritmo para encontrar o algoritmo timo o


seguinte. Encontre os dois smbolos que aparecem com menor freqncia,
no nosso caso B e D. Atribumos 0 para B e 1 para D. Combine estes dois
smbolos em um BD. Este novo smbolo ter freqncia igual a soma das
freqncias de B e D, no caso 2. Temos agora os seguintes smbolos A (3),
C (2) e BD (2), os nmeros entre parnteses so as freqncias.
Novamente devemos escolher os smbolos de menor freqncia, que so C
e BD. Atribumos o cdigo 0 ao smbolo C e 1 ao BD. Isto siginifica
adicionar 1 aos cdigos de B e D, que passam a valer 10 e 11
respectivamente. Os dois smbolos so combinados ento no smbolo CBD
de freqncia 4. Temos agora dois smbolos A (3) e CBD (4). Atribumos 0
ao smbolo A e 1 ao smbolo CBD. O smbolo ACBD o nico smbolo
restante e recebe o cdigo NULL de comprimento 0. A Figura arvhuf1
mostra a rvore binria que pode ser construda a partir deste exemplo.
Cada n representa um smbolo e sua freqncia.

Figura arvhuf1: rvore de Huffman

Vamos considerar outro exemplo em que temos

Removendo Ns de rvores Binrias


Para remover um n de uma rvore binria devemos considerar trs casos:
1. n sem filhos;
2. n com um unico filho;
3. n com dois filhos.
O caso de um n sem filhos o mais simples e significa apenas ajustar o
ponteiro de seu pai. A Figura remov0 ilustra este caso, onde o n com o
valor 8 removido. No caso do n ter um nico filho a mudana na rvore
tambm simples significa mover o n filho daquele ser removido uma
posio para cima como est ilustrado na Figura remove1, onde o n com
o valor 6 removido. O caso mais complexo o do n com dois filhos.
Neste caso devemos procurar o sucessor s (ou antecessor) do n dever
ocupar este lugar. Este n (sucessor) um descendente que est na
subrvore da direita do n e corresponde ao n mais esquerda desta
rvore. Ele no tem filhos esquerda e a sua rvore direita pode ser
movida para o lugar de s. A Figura remove2 ilustra o caso de remoo do
n com o valor 12. Observe que o n 13 (sucessor) assumiu o lugar do n
12.

Figura remove0: Removendo n (8) sem filhos.

Figura remov1: Removendo n (6) com um filho.


Figura remov2: Removendo n (12) com dois filhos.

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 */

/* agora iremos ver os dois primeiros casos, o no tem um


filho
no maximo */
if (p->esq == NULL)
rp = p->dir;
else
if (p->dir == NULL)
rp = p->esq;
else {
f=p;
rp = p->dir;
s = rp->esq; /* s e sempre o filho esq de rp
*/
while (s != NULL) {
f = rp;
rp = s;
s = rp->esq;
}
/* neste ponto, rp e o sucessor em ordem de p
*/
if (f != p) {
/* p nao e o pai de rp e rp == f->left */
f->esq = rp->dir;
/* remove o no rp de sua atual posicao e o
substitui pelo filho direito de rp
rp ocupa o lugar de p
*/
rp->dir = p->dir;
}
/* define o filho esquerdo de rp de modo que rp
ocupe o lugar de p
*/
rp->esq = p->esq;
}
/* insere rp na posicao ocupada anteriormente por p */
if (q == NULL)
tree = rp;
else
if (p == q->esq)
q->esq = rp;
else
q->dir = rp;
free(p);
return rp;
}

rvores rvores Binrias Balanceadas


Uma rvore binria balanceada, chamada de rvore AVL, uma rvore
binria na qual as alturas das duas subrvores de cada um dos ns nunca
diferem em mais de 1. O balanceamento de um n igual a diferena entre
as suas altura esquerda e direita. Portanto, cada n de uma rvore
balanceada tem balanceamento igual a -1, 0 ou 1, dependendo da
comparao entre as alturas esquerda e direita. Lembrando que a altura de
um n n da rvore o nmero de ns do maior caminho de n at um de
seus descendentes. As folhas tem altura 1. Uma rvore binria completa
com n>0 ns tem altura mnima, que igual a 1 + floor(log (n)). A Figura
arvbal mostra uma rvore binria balanceada. Os valores dentro do n so
altura do n e seu balanceamento.
Figura arvbal: rvore binria balanceada.
Caso a probabilidade de pesquisar uma chave em uma tabela seja a mesma
para todas as chaves, uma rvore binria balanceada ter a busca mais
eficiente. Infelizmente o mtodo de insero em rvores binrias
apresentado anteriormente no garante que a rvore permanecer
balanceada. Como j vimos a estrutura da rvore depende da ordem em
que as chaves so inseridas na rvore.
A Figura arvbali mostra possibilidades de insero na rvore e o que
ocorreria com o seu balanceamento. Cada insero que mantm a rvore
balanceada est indicada bor um B e as que desbalanceiam a rvore por
um D. Observe que uma rvore se torna desbalanceada quando o n
inserido se torna descendente esquerdo de um n que tinha anteriormente
um balanceamento de 1 ou se ele se tornar descendente direito de um n
que tinha anteriormente balanceamento de -1. Isto fcil de deduzir, por
exemplo, um n que tinha balanceamento 1 e recebe um descendente
direito aumenta sua altura em 1, portanto aumentando o seu
desbalanceamento.
Figura arvbali: rvore balanceada e suas possibilidades de insero

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.
Figura arvins: Insero em rvore binria

Observar que o n A tem balanceamento 1, isto significa que a subrvore


da esquerda tem altura no nula e maior em uma unidade que a da direita.
Ao inserirmos um n na subrvore da direita a sua altura aumenta de um e
o balanceamento passa para 2. Observar tambm que como o n mais
jovem a se tornar desbalanceado o A, o seu filho pela esquerda tem de ter
balalneamento igual a 0.

Para manter a rvore balanceada necessrio que a transformao na


rvore de tal modo que:

1. a rvore permanea uma rvore de busca binria;


2. a rvore continue a ser uma rvore balanceada.
Para isto vamos definir a operao de rotao em uma rvore. Uma rotao
pode ser direita ou esquerda. A Figura arvrot mostra uma rvore e os
resultados dos dois tipos de rotao sobre esta rvore esto mostrados na
Figura arvrota.

Figura arvrot: rvore original antes da rotao


Figura arvrota: Efeitos das rotaes

Um possvel algoritmo para rodar para a esquerda uma rvore enraizada


em p :

q = p->direita;
temp = q->esquerda;
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
ndice

You might also like