Você está na página 1de 16

Árvores Binárias de Pesquisa

• Apresentam uma relação de ordem


• A ordem é definida pela chave
• Operações:

Árvores
– inserir

AVL
– consultar
500
– excluir

300 800

Transparências da profa. Renata Galante da II/UFRGS 150 400 600 900


com permissão

Problemas com ABP Problemas com ABP


Exemplo: • Desbalanceamento progressivo
– Inserção: 10, 5, 15, 20, 25, 30, 35 • Exemplo:
– Inserção: 1, 13, 24, 27, 56 – inserção: 1, 13, 24, 27, 56

13
Alternativa de solução:
24
• Árvores balanceadas
• AVL
27

56

3 4
Balanceamento de Árvores Por Freqüência
• Distribuição equilibrada dos nós • Por freqüência de acesso
– otimizar as operações de consulta – Pressupõe distribuição não uniforme de acessos
– diminuir o número médio de comparações
• Distribuição
– uniforme
500 50%

– não uniforme
• chaves mais solicitadas mais perto da raiz
12% 400 800 25%
Balanceamento por distribuição
de acessos!
4% 600 900 5%

550 4%

5 6

Árvores balanceadas por ALTURA Árvores AVL

Uma árvore binária é Adelson-Velskii e Landis (1962)


completamente balanceada • Uma árvore AVL é uma árvore binária de
se a distância média dos nodos até a raiz for mínima pesquisa (ABP) construída de tal modo
A +3
que a altura de sua subárvore direita
difere da altura da subárvore esquerda de
-2
B C
no máximo 1, ou seja, o fator de nó deve
ser -1, 0, 1.
0 -1
D E
• Também chamada de árvore
balanceada.
• Fator de um nó G H 0
0

– Fator = altura_subarv_esq - altura_subarv_dir


Não é árvore AVL 0 I J 0

7 8
Exercício: Exercício: Resposta

Verifique quais das ABP são AVL: Verifique quais das ABP são AVL:

130 +1 120 -1

130 120
0 100 130 -2
-1 100 150 -1

100 150 100 130


0 +1 200 0 0 80 110 0 200 +1
80 120

80 200 80 110 200


120
0 110 0 150

110 150 AVL Não AVL

9 10

Exercício Exercício: Resposta


Verifique quais das ABP são AVL: Verifique quais das ABP são AVL:
42 42 0 42 0
42
-1
15 88 15 15 88 +1 -2 15 88 +2
88
0
+1
6 27 27 6 27 0 63 94 0 27 +1
63 94 63 63 0

20 57 71 20 57 71 0 20 0 57 71 0 0 20 0 57 71 0
AVL Não AVL
42 0 42

0 15
AVL: completamente
15 88 88 0
balanceada
6 27 0 6 27 0 0 63 94 0
63 94

11 12
Operações Operações

• por exemplo: INSERÇÃO • Como manter uma árvore AVL sempre


• deve ser preservada a propriedade AVL balanceada após uma inserção ou
exclusão?
– Através de uma operação de ROTAÇÃO
• Característica da operação
– preserva a ordem das chaves
– basta uma execução da operação de
Reestruturar rotação para tornar a árvore AVL
a árvore novamente

13 14

AVLNode AVLNode
public class AvlNode { public int getKey() {
protected int height; // Height return key;
protected int key; }
protected AvlNode left, right;
public void setKey(int key) {
public AvlNode ( int theElement ) { this.key = key;
this( theElement, null, null ); }
}
public AvlNode getLeft() {
public AvlNode ( int theElement, AvlNode lt, AvlNode rt ) { return left;
key = theElement; }
left = lt;
right = rt; public void setLeft(AvlNode left) {
height = 0; this.left = left;
} }
public int getHeight() {
return height; public AvlNode getRight() {
} return right;
}
public void setHeight(int height) {
this.height = height; public void setRight(AvlNode right) {
} this.right = right;
}
}

15 16
Balanceamento de Árvore AVL com Rotação Rotação Simples DIREITA
• Toda vez que uma subárvore fica com
um fator:
– positivo e sua subárvore da esquerda
Rotação Simples também tem um fator positivo
• à direita
• à esquerda
ROTAÇÃO SIMPLES À DIREITA
Rotação Dupla
• à direita
• à esquerda

17 18

Rotação Direita Rotação Direita

120 120 +1

110 150 +2 110 150 0

100 130 200 +1 100 130 200


0 0
80 80
0

19 20
Rotação Direita Rotação Direita

120 +1 120 +1 120 0

+2 110 150 0 Rotação


Direita
? +2 110 150 0 Rotação
Direita
0 100 150 0

+1 100 +1 100 80 110 130 200


130 200 130 200
0 0 0 0 0 0 0 0

80 80
0 0

21 22

Balanceamento de Árvore AVL com Rotação Métodos auxiliares

public class AvlTree {

Rotação Simples
private AvlNode root = null;

• à direita /** Retorna a altura da árvore */


private static int height ( AvlNode t ) {
return t == null ? 0 : t.height;
}

/** Retorna o maior valor ente lhs e rhs. */


k2 Nó k2 é a raiz de transformação private static int max ( int lhs, int rhs ) {
return lhs > rhs ? lhs : rhs;
}
k1
/** Retorna o fator de balanceamento da árvore com raiz t */
z

private int getFactor (AvlNode t) {


X, Y e Z são subárvores return height( t.left ) - height( t.right );
x y (vazias ou não) }

23 24
Rotação Direita Rotação Direita

k2 k1

Rotação 42 +1
Direita 42 +2
k1 z x k2

0 15 88 0
Incluir 4 +1 15 88 0
x y y z

private static AvlNode doRightRotation( AvlNode k2 ) { 0 6 27 0


AvlNode k1 = k2.left; +1 6 27 0
k2.left = k1.right;
k1.right = k2;
k2.height = max( height( k2.left ), height( k2.right ) ) + 1; 0 4
k1.height = max( height( k1.left ), k2.height ) + 1;
return k1;
}

25 26

Rotação Direita Ajustado!


Rotação Simples ESQUERDA

• Toda vez que uma subárvore fica com


um fator:
– negativo e sua subárvore da direita também
42 +2 15 0

tem um fator negativo


Rotação
Direita
+1 15 88 0 +1 6 42 0
ROTAÇÃO SIMPLES À ESQUERDA
+1 6 27 0 0 4 0 27 88 0

0 4

27 28
Rotação Simples ESQUERDA Rotação Simples ESQUERDA

120 -1 120 -1

0 100 130 -2 0 100 130 -2 Rotação


Esquerda
?
80 110 150 -1 80 110 150 -1

0 0 0 0
200 200
0 0

29 30

Rotação Simples ESQUERDA Rotação Simples ESQUERDA

k2
k1

120 120 Rotação


Esquerda k1
x k2 z

100 Rotação 100 150


130 Esquerda
z x y
y
80 110 130 200
80 110 150

200

31 32
Rotação Simples ESQUERDA Rotação Simples ESQUERDA

k2
k1

Rotação 42 -2
Esquerda k1 42 -1
x k2 z

0 0 15 88 -1
15 88 0 Incluir 90
z x y
y
0 67 94 1
private static AvlNode doLeftRotation( AvlNode k1 ) {
0 67 94 0
AvlNode k2 = k1.right;
k1.right = k2.left;
k2.left = k1; 0 90
k1.height = max( height( k1.left ), height( k1.right ) ) + 1;
k2.height = max( height( k2.right ), k1.height ) + 1;
return k2;
}

33 34

Rotação Simples ESQUERDA Rotação Dupla à Direita

• Toda vez que uma subárvore fica com


um fator:
Ajustado!

– positivo e sua subárvore da esquerda tem


42 -2
88 0 um fator negativo
Rotação

ROTAÇÃO DUPLA À DIREITA


Esquerda
0 15 88 -1 0 42 94 +1

0 67 94 1 0
15 0
67 90 0

0 90

35 36
Rotação Dupla à Direita Rotação Dupla à Direita

120 +1 120 +1

Rotação
+2 110 150 0 +2 110 150 0
Dupla
Direita
?
-1 80 130 200 -1 80 130 200
0 0 0 0

100 100

0 0

37 38

Rotação Dupla à Direita120 Rotação Dupla à Direita

120 k3 k3
110 150
Rotação
Esquerda k2 d
110 150 k1 d
100 130 200 1
k1 c
80 130 200 k2
a
80 DIREITA
a b
100 k2
120 b c
ESQUERDA
k1 k3
Rotação
100 150 Direita

2
a b c d
80 110 130 200
39 40
Rotação Dupla à Direita Rotação Dupla à Direita

k3
k2

Rotação 42 +1 42 +2
k1 d Dupla
Direita k1 k3

0 15 88 0 -1 15 0
k2 Incluir 34 88
a a b c d

0 6 27 0 0 6 27 -1
b c

private static AvlNode doDoubleRightRotation( AvlNode k3 ) { 34 0


k3.left = doLeftRotation( k3.left );
return doRightRotation( k3 );
}

41 42

Rotação Dupla à Direita Rotação Dupla à Direita

PASSO 1 PASSO 2
Rotação Esquerda Rotação Direita
Rotação Rotação
Dupla Dupla
42 +2 Direita Direita 27 0
42 +2
42 +2

-1 15 88 0 +1 15 42 0
+1 27 88 0
+1 27 88 0

0 6 27 -1 +1 0 6 0 34 88 0
+1 15 34 0
15 34 0

34 0 0 6
0 6

43 44
Rotação Dupla ESQUERDA Rotação Dupla ESQUERDA

• Toda vez que uma subárvore fica com um


fator:
– negativo e sua subárvore da direita tem um fator
positivo
120 -1

ROTAÇÃO DUPLA À ESQUERDA 0 100 130 -2

80 110 200 +1
0 0
150

45 46

Rotação Dupla ESQUERDA Rotação Dupla ESQUERDA


120
120

120 -1 100 130


100 130
Rotação
0 100 130 -2
Dupla
Esquerda
? 80 110 200
80 110 150

150
80 110 200 +1 200
0 0 120
DIREITA ESQUERDA
150

0 100 150

80 110 130 200


47 48
Rotação Dupla ESQUERDA Rotação Dupla ESQUERDA
k1
k1

120 120 ROTAÇÃO


a k2
DIREITA
a k3
Rotação
100
Dupla 100 150 b k3
130 Esquerda
k2 d

80 110 130 200


80 110 200 k2 c d
b c

150
k1 k3
ROTAÇÃO
ESQUERDA

a b c d
49 50

Rotação Dupla ESQUERDA Resumo: Rotações


positivo e f. e. positivo negativo e f. d. negativo
k1 k1 k2
k2 k1
k2 Rotação
Rotação
k1 k2 x k2 Esquerda k1 z
z Direita
a k3 x
Rotação
Dupla
k1 k3 x y y z y z x y

positivo e f. e. negativo negativo e f. d. positivo


Esquerda
k2 d
k1
a b c d Rotação
Rotação
Dupla a Dupla
b c k3 Esquerda
Direita k2 k2
private static AvlNode doDoubleLeftRotation (AvlNode k1) {
k1.right = doRightRotation( k1.right ); k1 k3 k2 d k1 k3
return doLeftRotation( k1 );
} a b c d b c a b c d

51 52
Exemplos de Rotação (Esquerda e Direita) Exemplos de Rotação (dentro da árvore)

• Considere a árvore abaixo, no qual 12 está entre 9 e 15. • Considere a árvore abaixo:
– Fazendo a rotação direita em 9, onde ficará 12? – Execute a rotação em 15. O que acontece com o nó 42 (que é pai de 15)?

– Terminada a rotação a direita, tente agora a rotação a esquerda em 15. – Execute agora a operação oposta em 42. O que acontece com 15 (que é pai de
42)?

50

15 42

15 43
9 22

6 23
4 12

17 30

53 54

Inserção de nodos em árvores AVL


Inserção em Árvores AVL Alguns Problemas

• Percorre-se a árvore verificando se a chave já existe ou não


220 – Em caso positivo, encerra a tentativa de inserção
– Caso contrário, a busca encontra o local correto de inserção do
novo nó
• Verifica-se se a inclusão tornará a árvore desbalanceada
120 300

– Em caso negativo, o processo termina


100 150
260 400 – Caso contrário, deve-se efetuar o balanceamento da árvore
• Descobre-se qual a operação de rotação a ser executada
• Executa-se a rotação
80 110 130 200 250 270 350 500

Inserir 140

55 56
Inserção em Árvore AVL

private AvlNode insert (int x, AvlNode t) { public boolean insert (int x) {


if( t == null ) t = new AvlNode( x, null, null );
// se chave já existe na árvore retorna false
else if( x<t.key ) t.left = insert( x, t.left );
else if( x>t.key) t.right = insert( x, t.right ); if (search (x)!=null) return false;
if ( getFactor(t) == 2 ) { // insere chave na árvore
if (getFactor (t.left)>0) t = doRightRotation( t );
root = insert (x, root);
else t = doDoubleRightRotation( t );
} return true;
else if ( getFactor(t) == -2 ) { }
if ( getFactor(t.right)<0 ) t = doLeftRotation( t );
else t = doDoubleLeftRotation( t );
}
t.height = max( height( t.left ), height( t.right ) ) + 1;
return t;
}

57 58

Remoção de nodos em árvores AVL Remoção em Árvore AVL

• Caso parecido com as inclusões. -1


• No entanto, nem sempre se consegue solucionar com 32
uma única rotação... -1 -1

• Remover elemento e retornar do pai do nó removido 16 48

até a raiz, verificando se cada nó do caminho precisa 0 0 -1


-1
ser balanceado 8 24 40 56
0 0 0 0
0
28 36 44 52 60

0 0
58 62

deletando 8

59 60
Remoção em Árvore AVL Remoção em Árvore AVL
-1 -2
32 32 rotação simples
-2 0 -1 à esquerda
-1
16 48 24 48

-1 0 -1 0 0 0 -1
24 40 56 16 28 40 56
0 0 0 0 0 0 0 0
0
28 36 44 52 60 36 44 52 60
rotação simples 0 0
0 0
à esquerda 58 62 58 62

volta recursivamete até a raiz, balanceando todos os


faz balanceamento de nó pai de nó deletado: nós que se encontrarem desbalanceados

61 62

Remoção em Árvore AVL Árvores AVL

0
48

0 -1

• Applet que simula árvore AVL:


32 56

0 0 0 0
http://webpages.ull.es/users/jriera/Docencia/AVL/AVL%20tree%20applet.htm
24 40 52 60

0 0 0 0 0 0
16 28 36 58 62
44

63 64