1 Estruturas de Dados com Jogos Capítulo 9 Árvores Balanceadas.
Árvores Balanceadas André Lopes Pereira Luiz Carlos Barboza Júnior.
Transcript of Árvores Balanceadas André Lopes Pereira Luiz Carlos Barboza Júnior.
Árvores Balanceadas
André Lopes Pereira
Luiz Carlos Barboza Júnior
Roteiro
Árvores de busca binárias: Organização; Algoritmos de busca, inserção e remoção
em árvores de busca (custos envolvidos); Desvantagens de uma árvore
desbalanceada: Aplicação de AVL; Aplicação de nó crítico e fator de equilíbrio; Rotações simples de dupla; AVL implementada em C.
Árvores de busca binária
Busca
Inserir
Deletar
Todas as chaves da sub-árvore à esquerda são menores do que a chave da raiz, e as chaves da sub-árvore à direita são maiores. Essa regra define árvore de busca binária.
Definição:
Operações:
BuscaBusca (root, x)
Entrada: root (ponteiro pra raiz da árvore) e x número a ser procurado
Saída: node (ponteiro que aponta para o nó contendo x ou nil se o nó não existir)
início
se root = nil ou root^.key então node := root
// root^ e´o conteudo do endereco de root
senao
se x < root^.key então Busca (root^.left,x)
senão Busca (root^.right,x)
fim.
InserirInserir (root,x)
Entrada: root (ponteiro pra raiz da árvore) e x número a ser inserido
Saída: árvore modificada
início
se root = nil então
crie um novo nó apontado por child;
root := child;
root^.key := x;
senao
node := root;
child := root; //para inicializar e ele nao seja null
enquanto node != nil e child != nil faça
se node^.key = x então child := nil
senão
parent := node;
se x < node^.key então node := node^.left
senão node := node^.right
se child != nil então
crie um novo nó apontado por child;
child^.key := x;
child^.left := nil; child^.right := nil;
se x < parent^.key então parent^.left := child
senão parent^.right := child
fim
DeletarDeletar (root,x)
Entrada: root (ponteiro pra raiz ) e x número a ser deletado
Saída: árvore modificada
início
node := root;
enquanto node != nil e node^.key != x faça
parent := node;
se x < node^.key então node := node^.left;
senão node := node^.right;
se node = nil então imprima ("x não está na árvore"); sair
se node != root então
se node^.left = nil então
se x <= parent^.key então parent^.letf := node^.right
senão parent^.right := node^.right
senão se node^.right = nil então
se x <= parent^.key então parent^.left := node^.left
senão parent^.right := node^.left
senão // o caso de 2 filhos
node1 := node^.left
parent1 := node
enquanto node^.right != nil do
parent1:= node1;
node1:= node1^.right;
parent1^.right := node1^.left
node^.key := node1^.key
fim
Deletar: folhas
(...)
se node^.left = nil então
se x <= parent^.key
então
parent^.letf := node^.right
senão
parent^.right := node^.right
senão se node^.right = nil então
se x <= parent^.key
então
parent^.left := node^.left
senão
parent^.right := node^.left
(...)
Deletar: nó com único filho
(...)
se node^.left = nil então
se x <= parent^.key
então
parent^.letf := node^.right
senão
parent^.right := node^.right
senão se node^.right = nil então
se x <= parent^.key
então
parent^.left := node^.left
senão
parent^.right := node^.left
(...)
Deletar: nó com dois filhos
(...)
senão // o caso de 2 filhos
node1 := node^.left
parent1 := node
enquanto node^.right != nil do
parent1:= node1;
node1:= node1^.right;
parent1^.right := node1^.left
node^.key := node1^.key
fim
Custos envolvidos
Pior caso: Percorrer a árvore da raiz até a folha mais distante
para localizar o nó desejado
Tempo de execução dos outros passos é constante
Custo
O (log n)Árvore balanceada
O (n)Lista encadeada
AVL
AVL (Adel’son-Vel’skii e Landis)
Árvore de busca binária que, para cada nó, a diferença entre as alturas de suas sub-árvores é no máximo 1
Definição:
Balance
Fator que indica a diferença entre a altura das sub-árvores da esquerda e da direita, precedido do sinal + (caso a da direita seja maior) ou - (caso a maior seja a da esquerda).
Definição:
Balanceatual
InserçãoEsq ou Dir
Novobalance
0 Esq. | Dir. -1/0 | +1/0
-1 Dir. -1/0
+1 Esq. +1/0
-1 Esq. -1/Deseq.
+1 Dir. +1/Deseq.
BalanceBalance (root)
Entrada: root (ponteiro pra raiz da arvore)
Saída: todos os nós da árvore com o valor de balance
início
se root = nil
altura := -1
senão root^.left = nil e root^.right = nil então
altura := 0;
root^.balance := 0;
// se o no for um folha seu balance e´ 0 (zero)
senão
Esq := Balance (root^.left);
Dir := Balance (root^.right);
root^.balance := Dir - Esq;
altura := Max (Esq, Dir);
retorna (altura + 1)
fim
Nó crítico
(...)
se balance mudou de 0 para +1 ou -1 então retorne sim
se balance mudou de +1 ou -1 para 0 então retorne não
se a resposta for sim então
se o sim for pela direita então balance := balance + 1
se o sim for pela esquerda então balance := balance - 1
se balance => 2 ou balance <= -2 então
esse é o nó crítico. Aplique a rotação de acordo com a tabela:
Balance
Inserirà
Na sub-árvore da
Rotação
-1 Esq. Left Simples(horário)
-1 Esq. Right Dupla(horário)
+1 Dir. Left Dupla(anti-horário)
+1 Dir. Right Simples(anti-horário)
+ 1
Rotação simples
Temp := B^.dir;
B^.dir := A;
A^.esq := temp;
Rotação dupla
Temp := B^.dir;
B^.dir := B^.dir^.esq;
A^.esq := B^.dir^.dir;
Temp^.esq := B;
Temp^.dir := A;
Conclusão
Tipos de dados abstratos que manipulam estas três operações são chamados de dicionários (ordem lexicográfica);
A eficiência da árvore de busca é diretamente relacionada à sua altura. A estratégia é manter a árvore com a altura mínima possível utilizando as regras de AVL;