Você está na página 1de 44

rvores Binrias de Busca

Definio

Uma rvore Binria de Busca possui as mesmas propriedades de uma AB, acrescida da seguinte propriedade: Para todo n da rvore, se seu valor X, ento:

Os ns pertencentes a sua sub-rvore esquerda possuem valores menores do que X; Os ns pertencentes a sua sub-rvore direita possuem valores maiores do que X. Um percurso em in-ordem nessa rvore resulta na seqncia de valores em ordem crescente
2/30

Exemplo
17 13 1 3 99 100 400

Caractersticas

Se invertessemos as propriedades descritas na definio anterior, de maneira que a subrvore esquerda de um n contivesse valores maiores e a sub-rvore direita valores menores, o percurso em-ordem resultaria nos valores em ordem decrescente Uma rvore de busca criada a partir de um conjunto de valores no nica: o resultado depende da ordem de insero dos dados

4/30

Caractersticas

A grande utilidade da rvore binria de busca armazenar dados contra os quais outros dados so freqentemente verificados (busca!) Uma rvore binria de busca armazenada dinamicamente e em geral sofre alteraes (inseres e remoes de ns) aps ter sido criada
5/30

Listas versus ABB

O tempo de busca estimado pelo nmero de comparaes entre chaves. Em listas de n elementos, temos:

Sequenciais (Array): O(n) se no ordenadas; ou O(log2n), se ordenadas Encadeadas (Dinmicas): O(n)

As ABB constituem a alternativa que combina as vantagens de ambos: so dinmicas e permitem a busca binria O(log2n)
6/30

Operaes em ABB

Busca

Insero mantendo as propriedades de ABB

Remoo mantendo as propriedades de ABB

7/30

Busca

Passos do algoritmo de busca:

Se a rvore vazia, fim e no achou. Se chave da raiz igual chave procurada, termina busca com sucesso. Seno: Repita o processo para a sub-rvore esquerda, se chave da raiz maior que a chave procurada; se for menor, repita o processo para a sub-rvore direita. Caso o n contendo o valor pesquisado seja encontrado, retorne um ponteiro para o n; caso contrrio, retorne um ponteiro nulo.

Faa a analogia com a busca binria feita em arrays.

8/30

Verifique em que condies a busca em ABB tem performance O(log2n)

Considere:

uma comparao por nvel; n ns no total Quanto menor a altura da rvore, menor o nmero de comparaes; Altura mnima de uma AB de n ns O(log2n) AB perfeitamente balanceadas (PB) tm altura mnima.
9/30

Portanto:

Logo: ABB ideais so PB (e deveriam ser mantidas como tal, porm so dinmicas.......)

Busca (recursiva)
pno busca(tree raiz, tipo_elem valor){

if (raiz == NULL) return NULL;


if (valor == raiz->info) return raiz; if (valor < raiz->info) return busca(raiz->esq, valor); else return busca(raiz->dir, valor); }

10/30

Busca (no recursiva)


pno busca(tree raiz, tipo_elem valor){ pno p; p = raiz; while (p != NULL){ if (p->info == valor) return p; else if (valor > p->info) p = p->dir; else p = p->esq; } return p;

11/30

Recursiva versus No-Recursiva


Em relao a tempo (nmero de comparaes): equivalentes

Em relao a espao (memria): a recursiva requer espao extra para as chamadas recursivas. Esse espao extra diretamente proporcional (linear) altura da rvore. (VERIFIQUE!)

12/30

Custo da busca em ABB

Pior caso: como o nmero de passos determinado pela altura da rvore, o pior caso a rvore degenerada (altura = n). Altura da ABB depende da sequncia de insero das chaves...

Considere, p.ex., o que acontece se uma sequncia ordenada de chaves inserida... Seria possvel gerar uma rvore balanceada com essa mesma sequncia, se ela fosse conhecida a priori. Como?

Busca tima: rvore de altura mnima (perfeitamente balanceada) Busca eficiente: rvore razoavelmente balanceada...(rvore balanceada)
13/30

rvore Binria Balanceada

Para cada n, as alturas de suas duas subrvores diferem de, no mximo, 1

B D

C E
D

B
E F

14/30

rvore Binria Perfeitamente Balanceada


O nmero de ns de suas sub-rvores esquerda e direita difere em, no mximo, 1 a rvore de altura mnima para o conjunto de chaves Toda AB Perfeitamente Balanceada Balanceada, sendo que o inverso no necessariamente verdade

15/30

Insero (operaes em ABB's)

Passos do algoritmo de insero:

Procure um local para inserir a nova chave, comeando a procura a partir do n-raiz: Para cada n-raiz, compare:

se a nova chave for menor do que o valor no n-raiz, repita o processo para sub-rvore esquerda; ou se a nova chave for maior que o valor no n-raiz, repita o processo para sub-rvore direita.

Se um ponteiro (filho esquerdo/direito de um n-raiz) nulo atingido, coloque o novo n como sendo raiz dessa subrvore vazia. A insero sempre se d como n folha: no exige deslocamentos!
16/30

Insero

Para entender o algoritmo, considere a insero do conjunto de nmeros, na seqncia {17, 99, 13, 1, 3, 100, 400}
No incio, a ABB est vazia!

17/30

Insero

O nmero 17 ser inserido tornando-se o n raiz A insero do 99 iniciase na raiz. Compara-se 99 c/ 17. Como 99 > 17, 99 deve ser colocado na subrvore direita do n contendo 17 (subrvore direita, inicialmente, nula)

Raiz 17 99

18/30

Insero

A insero do 13 inicia-se na raiz Compara-se 13 c/ 17. Como 13 < 17, 13 deve ser colocado na sub-rvore esquerda do n contendo 17 J que o n 17 no possui descendente esquerdo, 13 inserido como raiz dessa sub-rvore

Raiz 17 13

99

19/30

Insero

Repete-se o procedimento para inserir o valor 1 1<17, ento ser inserido na sub-rvore esquerda Chegando nela, encontra-se o n 13, 1<13 ento ele ser inserido na sub-rvore esquerda de 13

Raiz 17 13 1

99

20/30

Insero

Repete-se o procedimento para inserir o elemento 3:

Raiz 17 13 1 3

3 < 17; 3 < 13 3>1

99

21/30

Insero

Repete-se o procedimento para inserir o elemento 100:


Raiz 17 13 1 3

99
100

100 > 17 100 > 99

22/30

Insero

Repete-se o procedimento para inserir o elemento 400:


Raiz 17 13 1 3

99
100 400

400 > 17 400 > 99 400 > 100

23/30

Insero

O algoritmo de insero no garante que a rvore resultante seja perfeitamente balanceada ou mesmo apenas balanceada

Funo Recursiva de Insero


Seja

uma funo recursiva que insere uma chave x numa ABB, se ela j no estiver l. Retorna o ponteiro para o n que contm x.
Essa

funo usada para a construo de uma ABB.

pno busca_insere(tipo_elem x, tree raiz);

x: chave para inserir; raiz: raiz da rvore onde deve inserir; busca_insere: retorna endereo onde est x

pno busca_insere(tipo_elem x, tree raiz){ if (raiz == NULL) { /*inserir x como raiz da rvore*/ raiz = malloc(sizeof(tree)); raiz->info = x; raiz->esq = NULL; raiz->dir = NULL; return raiz; } if (x < raiz->info) return busca_insere(x, raiz->esq); if (x > raiz->info) return busca_insere(x, raiz->dir); return raiz; }

Acrescente um parmetro booleano para indicar se houve a insero ou no.

Custo da Operao de Insero

A insero requer uma busca pelo lugar da chave, portanto, com custo de uma busca qualquer (tempo proporcional altura da rvore). O custo da insero, aps a localizao do lugar, constante; no depende do nmero de ns. Logo, tem complexidade anloga da busca.

Remoo (operaes em ABB's)

Casos a serem considerados no algoritmo de remoo de ns de uma ABB:

Caso 1: o n folha

O n pode ser retirado sem problema;

Caso 2: o n possui uma sub-rvore (esq./dir.)

O n-raiz da sub-rvore (esq./dir.) pode substituir o n eliminado;


O n cuja chave seja a menor da sub-rvore direita pode substituir o n eliminado; ou, alternativamente, o de maior valor da sub-rvore esquerda pode substitu-lo.

Caso 3: o n possui duas sub-rvores

28/30

Remoo Caso 1

Caso o valor a ser removido seja o 15 pode ser removido sem problema, no requer ajustes posteriores

11
9 14

10

12 13

15

29/30

Remoo Caso 1

Os ns com os valores 10 e 13 tambm podem ser removidos!

11 9 14 12 13
30/30

10

Remoo Caso 2

Removendo-se o n com o valor 5 Como ele possui uma sub-rvore direita, o n contendo o valor 6 pode ocupar o lugar do n removido

3 1

5
6 7
31/30

Remoo Caso 2

Caso existisse um n com somente uma sub-rvore esquerda, seria anlogo.

3
1 6 7

32/30

Remoo Caso 3

Eliminando-se o n de chave 11 Neste caso, existem 2 opes:

11
9 14

O n com chave 10 pode ocupar o lugar do nraiz, ou O n com chave 12 pode ocupar o lugar do n-raiz

10

12

15 13
33/30

Remoo Caso 3

Esse terceiro caso, tambm se aplica ao n com chave 14, caso seja retirado.

12

Nessa configurao, os ns com chave 13 ou 15 poderiam ocupar seu lugar.

9
10

14
13

15

34/30

Considere o contexto no programa principal, para a remoo da chave x:


... if (busca_remove(raiz, x)) printf(houve a remoo); else printf(x no pertence rvore); ...

boolean busca_remove(tree raiz, tipo_elem x){


/*retorna true se removeu x; false, se x no estava na rvore*/

if (raiz == NULL) /*rvore vazia; x no est na rvore*/ return FALSE; if (raiz->info == x) { /*achou x: eliminar*/ removerNo(raiz); /*se alterar raiz no procedimento, altera aqui*/ return TRUE; }

if (raiz->info < x) /*buscar e remover na sub-rvore direira*/ return busca_remove(raiz->dir, x); else /*buscar e remover na sub-rvore esquerda*/ return busca_remove(raiz->esq, x);
} Repare no efeito da passagem por endereo da varivel raiz nas funes removerNo() e busca_remove()

void removerNo(pno p){ /* p o ponteiro para o n a ser removido; retorna em p o ponteiro para o n que o substituiu */
pno q; p p ou

if (p->esq == NULL){ /* substitui por filho direita */ q = p; p = p->dir; free(q);


} else if (p->dir == NULL) { /* substitui por filho esquerda */ q = p; p = p->esq; free(q); } else

substituimenoradireita(p, p->dir); /*alternativamente:substituirmaioraesquerda(p,p->esq)*/ } p Repare que ao alterar p, alteramos o parmetro atual (veja quem ele na funo busca_remove)

void substituimenoradireita(pno p, pno suc){ /*encontra o sucessor de p, ou seja, o descendente mais a esquerda da sub-arvore direita de p. um n terminal seu contedo copiado em q e ele ser removido*/ pno q; p
Suc

ou

p
Suc

if (suc->esq == NULL){ p->info = suc->info; /*remover suc*/ q = suc; suc = suc->dir; /*altera p->dir*/ free(q); } else substituimenoradireita(p, suc->esq);

} p
Suc

Exemplo
Raiz

Suc0
substituimenoradireita(p, p->dir) substituimenoradireita(p,Suc0->esq)

50
P 30 35
Suc0

Suc1

60 40 55
45 38 q 70

10
Suc1

35

Custo da Operao de Remoo

A remoo requer uma busca pela chave do n a ser removido, portanto, com custo de uma busca qualquer (tempo proporcional altura da rvore). O custo da remoo, aps a localizao do n depender de 2 fatores:

do caso em que se enquadra a remoo: se o n tem 0, 1 ou 2 sub-rvores; se 0 ou 1 filho, custo constante. de sua posio na rvore, caso tenha 2 sub-rvores (quanto mais prximo do ltimo nvel, menor esse custo)

Repare que um maior custo na busca implica num menor custo na remoo pp. dita; e vice-versa. Logo, tem complexidade dependente da altura da rvore.

Consequncias das operaes de insero e eliminao


Uma ABB balanceada ou perfeitamente balanceada tem a organizao ideal para buscas. Inseres e eliminaes podem desbalancear uma ABB, tornando futuras buscas ineficientes. Possvel soluo:

Construir uma ABB inicialmente perfeitamente balanceada (algoritmo a seguir) aps vrias inseres/eliminaes, aplicamos um processo de rebalanceamento (algoritmo a seguir)

Algoritmo para criar uma ABB Perfeitamente Balanceada


1.

2.

3.

4.

5.

Ordenar num array os registros em ordem crescente das chaves; O registro do meio inserido na ABB vazia (como raiz); Tome a metade esquerda do array e repita o passo 2 para a sub-rvore esquerda; Idem para a metade direita e sub-rvore direita; Repita o processo at no poder dividir mais.

Algoritmo de Rebalanceamento
1.

2.

Percorra em In-ordem a rvore para obter uma sequncia ordenada em array. Repita os passos 2 a 5 do algoritmo de criao de ABB PB.

ABB: Resumo

Boa opo como ED para aplicaes de pesquisa (busca) de chaves, SE rvore balanceada O(log2n) Inseres (como folhas) e Eliminaes (mais complexas) causam desbalanceamento. Inseres: melhor se em ordem aleatria de chaves, para evitar linearizao (se ordenadas) Para manter o balanceamento, 2 opes: como descrito anteriormente rvores AVL