Árvores de busca

125
Árvores de Busca

Upload: corin

Post on 15-Jan-2016

27 views

Category:

Documents


0 download

DESCRIPTION

Árvores de Busca. Árvores de Busca. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Árvores de Busca

Árvores de Busca

Page 2: Árvores de Busca

2

Árvores de Busca

Uma árvore que suporta eficientes operações de busca, inclusão e exclusão é chamada de árvore de busca. A árvore é usada para armazenar um conjunto finito de chaves obtidas de um conjunto totalmente ordenado de chaves K. Cada nó da árvore contém um ou mais chaves e todas as chaves na árvore são únicas, sem duplicação.A diferença entre uma árvore comum e uma árvore de busca é que, nesta última, as chaves não aparecem em nós arbitrários. Existe um critério de ordenação de dados que determina aonde cada chave pode figurar na árvore em relação às demais.Serão apresentadas as árvores de busca: de M caminhos (M-Way) binárias.

Page 3: Árvores de Busca

3

Binary Search Tree (BST)

Definição (Árvore de busca M-way)Uma árvore de busca M-way  T é um conjunto finito de chaves. Ou

o conjunto é vazio, T = ; ou o conjunto é constituído de n sub árvores M-way T1 , T2 ,..., Tn-1,

e n-1 chaves, k1 , k2 ,..., kn-1, T = {T0,k1, T1, k2, ..., kn-1, Tn-1}

aonde 2 n M, tal que as chaves e os nós satisfaçam às seguintes propriedades de ordenação de dados: As chaves em cada nó são distintas e ordenadas, i.e., k i<ki+1

para 1 i n-1 Todas as chaves contidas na sub árvore T i-1 são menores do

que ki. A árvore Ti-1 é chamada sub árvore da esquerda com respeito à chave ki.

Todas as chaves contidas na sub árvore T i são maiores do que ki. A árvore Ti+1 é chamada sub árvore da direita com respeito à chave ki.

Page 4: Árvores de Busca

4

Exemplo de árvore de busca M-Way

Page 5: Árvores de Busca

5

Binary Search Tree (BST)

Definição (Árvore Binária de Busca)  A Árvore Binária de Busca    T é um conjunto

finito de chaves. Ou o conjunto é vazio, T = ; ou o conjunto consiste da raiz r e exatamente duas Árvores Binárias de Busca TL e TR , T={r,TL,TR}, tais que as seguintes propriedades sejam satisfeitas: 1. Todas as chaves contidas na sub árvore da

esquerda, TL, são menores do que r. 2. Todas as chaves contidas na sub árvore da

direita, TR , são maiores do que r.

Page 6: Árvores de Busca

6

Exemplo de árvore binária de busca

Page 7: Árvores de Busca

7

Busca em Árvores de Busca M-Way

Busca do objeto x inicia na raizSe a raiz estiver vazia a busca falhaAs chaves contidas na raiz são examinadas para verificar se o objeto buscado está presenteSe o objeto não estiver presente três casos podem ocorrer: Objeto buscado é menor do que k1

a busca prossegue em T0; Objeto buscado é maior do que kn-1

a busca prossegue em Tn-1; Existe um i tal que ki < x < ki+1

a busca prossegue em Ti

Page 8: Árvores de Busca

8

Busca em Árvores Binárias de Busca

Semelhante à busca em árvores de busca M-WayApenas cada nó só possui um objeto e duas sub árvores

Page 9: Árvores de Busca

9

Árvore Binária Perfeita

Definição (Árvore Binária Perfeita) A Árvore Binária Perfeita de altura h 0

é um árvore binária T={r,TL,TR} com as propriedades: 1. Se h=0, então TL = e TR = .

2. Caso contrário, h>0, caso no qual ambos TL e TR são Árvores Binárias Perfeitas de altura h -1.

Page 10: Árvores de Busca

Implementação Java

Page 11: Árvores de Busca

11

Implementação de Árvores de Busca

Page 12: Árvores de Busca

12

Interface SearchTree

// pgm10_01.javapublic interface SearchTree extends Tree, SearchableContainer{ Comparable findMin (); Comparable findMax ();}

Page 13: Árvores de Busca

13

Classe BinarySearchTree

// pgm10_02.java

public class BinarySearchTree

extends BinaryTree

implements SearchTree

{

// ...

}

Page 14: Árvores de Busca

14

Classe Association

public class Association extends AbstractObject{ protected Comparable key; protected Object value;

// ...}

// só aparece por causa de getKey

Page 15: Árvores de Busca

15

Métodos da Classe Association

public class Association extends AbstractObject{ protected Comparable key; protected Object value; public Association (Comparable key, Object value) {

this.key = key; this.value = value;

} public Association (Comparable key)

{ this (key, null); } public Comparable getKey ()

{ return key; } public Object getValue ()

{ return value; } // ...}

Page 16: Árvores de Busca

16

Métodos da Classe BinarySearchTree

getLeftBSTgetRightBSTfindfindMininsertattachKeybalancewithdraw

Page 17: Árvores de Busca

17

Métodos getLeftBST e getRightBST

// pgm10_03.javapublic class BinarySearchTree extends BinaryTree implements SearchTree{ private BinarySearchTree getLeftBST()

{ return (BinarySearchTree) getLeft(); } private BinarySearchTree getRightBST()

{ return (BinarySearchTree) getRight(); } // ...}

Page 18: Árvores de Busca

18

Método find// pgm10_04.javapublic class BinarySearchTree extends BinaryTree implements SearchTree{ public Comparable find (Comparable object) {

if(isEmpty()) return null;

int diff = object.compare((Comparable) getKey()); if(diff == 0)

return (Comparable) getKey(); else

if(diff < 0) return getLeftBST().find(object);

else return getRightBST().find(object);

}}

Page 19: Árvores de Busca

19

Método findMin

public Comparable findMin () {

if(isEmpty()) return null;

elseif(getLeftBST().isEmpty())

return (Comparable) getKey();else

return getLeftBST().findMin(); } // ...

Page 20: Árvores de Busca

20

Inserção de itens em BST

A inclusão de nós em árvores de busca deve ser precedida de uma operação de busca. Esta operação indica se o nó buscado já existe na árvore e, em caso de não existência, o local aonde deve ser feita a inclusão. Convém lembrar que uma busca sempre termina em folha e os nós a incluir serão incluídos como filhos da folha aonde se encerrou a busca.

Page 21: Árvores de Busca

21

Método insert (1)

// pgm10_05.javapublic class BinarySearchTree extends BinaryTree implements SearchTree{ public void insert (Comparable object) {

if(isEmpty()) attachKey (object);

Page 22: Árvores de Busca

22

Método insert (2)

else {

int diff = object.compare((Comparable) getKey()); if(diff == 0)

throw new IllegalArgumentException( “chave duplicada");

if(diff < 0)getLeftBST().insert(object);

elsegetRightBST().insert(object);

} balance();

}}

Page 23: Árvores de Busca

23

Métodos attachKey e balance

public void attachKey (Object object) {

if(!isEmpty()) throw new InvalidOperationException();

key = object; left = new BinarySearchTree(); right = new BinarySearchTree();

}

protected void balance() {}

Page 24: Árvores de Busca

24

Remoção de itens em BST

A exclusão de nós em árvores de busca pode configurar um de 3 casos. Se o nó não tiver filhos pode ser excluído sem exigir

ajustamento da árvore. Se o nó a excluir tiver apenas uma sub árvore, este nó

pode ser excluído e deve ser substituído por seu filho único.

Se o nó a excluir tiver mais de um filho, para que ele possa ser excluído, deve ser substituído por seu antecessor ou seu sucessor em ordem infixa. O nó substituto deve ser excluído da sua posição gerando outro processo de exclusão.

Considerando o caso do sucessor em ordem infixa, o nó a ser excluído deve ser substituído pelo nó obtido alcançando-se o nó mais à esquerda da sub árvore direita do nó a excluir.

Page 25: Árvores de Busca

25

Remoção de itens em BST

Remoção do nó (4) folha em BST

Remoção do nó (1) não folha em BST

Page 26: Árvores de Busca

26

Método withdraw (1)// pgm10_06.javapublic class BinarySearchTree extends BinaryTree implements SearchTree{ public void withdraw (Comparable object) {

if(isEmpty()) throw new IllegalArgumentException(

"objeto não encontrado");

int diff = object.compare ((Comparable) getKey()); if(diff == 0) {

if(!getLeftBST().isEmpty()) {

Comparable max = getLeftBST().findMax(); key = max; getLeftBST().withdraw(max);

}

Page 27: Árvores de Busca

27

Método withdraw (2) else

if(!getRightBST().isEmpty()) {

Comparable min = getRightBST().findMin();

key = min; getRightBST().withdraw(min);

} else

detachKey(); } else

if(diff < 0) getLeftBST().withdraw(object);

else getRightBST().withdraw(object);

balance(); } // ...}

Page 28: Árvores de Busca

Árvores de Busca AVL

Page 29: Árvores de Busca

29

Conceito de AVL

Adelson-Velskii e Landis propuseram as condições de balanceamento para uma árvore binária que recebeu como sigla suas iniciais.

Definição (Condição de equilíbrio AVL)  Uma árvore binária vazia é AVL balanceada  . Uma árvore binária não-vazia, T={r,TL,TR} , é AVL balanceada se tanto TL quanto TR forem AVL balanceadas e |hL-hR|<=1

aonde hL é a altura of TL e hR é a altura of TR .

Page 30: Árvores de Busca

Implementação de árvores AVL

Page 31: Árvores de Busca

31

Classe AVLTree

// pgm10_07.java

public class AVLTree

extends BinarySearchTree

{

protected int Height;

// ...

}

Page 32: Árvores de Busca

32

Construtor

// pgm10_08.javapublic class AVLTree extends BinarySearchTree{ protected int Height;

public AVLTree() { Height = -1; }

// ...}

Page 33: Árvores de Busca

33

Métodos getHeight, adjustHeight e getBalanceFactor

public int getHeight () { return Height; }

protected void adjustHeight() {

if(isEmpty()) Height = -1;

else Height = 1 + Math.max(left.getHeight(),

right.getHeight()); } protected int getBalanceFactor() {

if(isEmpty()) return 0;

else return left.getHeight() - right.getHeight();

}

Page 34: Árvores de Busca

34

Inserção de itens em Árvores AVL

1o. Passo – Inserir o item2o. Passo – Balancear a árvore

Page 35: Árvores de Busca

35

Balanceamento de Árvores AVL

O balanceamento de árvores AVL é feito por operações chamadas de rotações, que podem ser: Rotações simples (LL e RR) Rotações duplas (LR e RL)

Page 36: Árvores de Busca

36

Rotações simples

A rotação LL ocorre quando um nó (B) tem a sub árvore da esquerda maior do que a da direita e seu filho da esquerda (A) tem sub árvore da esquerda maior do que a da direitaA rotação RR ocorre quando um nó (B) tem a sub árvore da direita maior do que a da esquerda e seu filho da direita (A) tem sub árvore da direita maior do que a da esquerda

Page 37: Árvores de Busca

37

Rotações duplas

A rotação LR ocorre quando um nó (C) tem a sub árvore da esquerda maior do que a da direita e seu filho da esquerda (A) tem sub árvore da direita maior do que a da esquerda. Aplica-se uma rotação RR a A seguida de uma rotação LL aplicada a C.A rotação RL ocorre quando um nó (C) tem a sub árvore da direita maior do que a da esquerda e seu filho da direita (A) tem sub árvore da esquerda maior do que a da direita. Aplica-se uma rotação LL a A seguida de uma rotação RR aplicada a C.

Page 38: Árvores de Busca

38

Rotação Simples LL

Page 39: Árvores de Busca

39

Propriedades das rotações simples

Existem três propriedades importantes da rotação LL:

1. A rotação não destrói a propriedade de ordenação de dados e, portanto, o resultado ainda é uma árvore de busca. A sub árvore AL permanece entre os nós A e B, e a sub árvore BR fica à direita do nó B.

2. Após a rotação tanto A quanto B são AVL balanceadas. Os nós A e B ficam com fator de balanceamento igual a zero.

3. Após a rotação a árvore permanece com a altura original. A inclusão do item não aumenta a altura da árvore.

Page 40: Árvores de Busca

40

Rotações Duplas

Page 41: Árvores de Busca

41

Balanceamento de árvores AVL

Os desbalanceamentos e as rotações de equilíbrio correspondentes podem ser enquadrados em seis categorias, ou casos, adiante descritos. O ancestral mais novo, desbalanceado, do novo nó inserido é ya. Seu filho na direção do desbalanceamento é s. Os sufixos l e r representam filho mais velho e filho mais novo, respectivamente:

Page 42: Árvores de Busca

42

Categorias de rotações

1o caso: O novo nó é incluído na sub árvore esquerda da sub árvore esquerda do nó ya. Este caso tem solução chamada de rightrotation ou rotação LL2o caso: O novo nó é incluído na sub árvore direita da sub árvore direita do nó ya. Este caso tem solução chamada de leftrotation ou rotação RR3 o caso: O novo é incluído na sub árvore esquerda da sub árvore direita do filho mais velho de ya (rotação LR)4 o caso: O novo nó é incluído na sub árvore direita da sub árvore direita do filho mais velho de ya (LR)5 o caso: O novo nó é incluído na sub árvore direita da sub árvore esquerda do filho mais novo de ya (RL)6 o caso: O novo nó incluído na sub árvore esquerda da sub árvore esquerda do filho mais novo de ya (RL)

Page 43: Árvores de Busca

43

Rotação LL

1o caso: O novo nó é incluído na sub árvore esquerda da sub árvore esquerda do nó ya. Este caso tem solução chamada de rightrotation ou rotação LL Inicialmente (*ya).bal = +1 (*s).bal = 0 A rotação consiste em: s (*ya).left temporário (*s).right (*s).right ya (*ya).left temporário

Page 44: Árvores de Busca

44

Rotação LL

Page 45: Árvores de Busca

45

Rotação RR

2 o caso: O novo nó é incluído na sub árvore direita da sub árvore direita do nó ya. Este caso tem solução chamada de leftrotation ou rotação RR. Inicialmente (*ya).bal = -1 (*s).bal = 0 A rotação consiste em: s (*ya).right temporário ya (*s).left ya (*ya).right temporário

Page 46: Árvores de Busca

46

Rotação RR

Page 47: Árvores de Busca

47

Rotação LR

3 o caso: O novo é incluído na sub árvore esquerda da sub árvore direita do filho mais velho de ya. Inicialmente (*ya).bal = + 1 (*s).bal = 0 A rotação consiste em: s ya.left q (*s).right temporário (*q).left (*q).left s (*s).right temporário temporário (*q).right (*q).right ya (*ya).left temporário

Page 48: Árvores de Busca

48

Rotação LR

Page 49: Árvores de Busca

49

Rotações LR e RL

4 o caso: O novo nó é incluído na sub árvore direita da sub árvore direita do filho mais velho de ya. Inicialmente (*ya).bal = +1 (*s).bal = 0 A rotação é a mesma do caso anterior

5 o caso: O novo nó é incluído na sub árvore direita da sub árvore esquerda do filho mais novo de ya. Inicialmente (*ya).bal = -1 (*s).bal = 0 A rotação consiste em: s (*ya).right q (*s).left temporário (*q).right (*q).right s (*s).left temporário temporário (*q).left (*q).left ya (*ya).right temporário

Page 50: Árvores de Busca

50

Rotação LR

Page 51: Árvores de Busca

51

Rotação RL

Page 52: Árvores de Busca

52

Classe AVLTree

public class AVLTree

extends BinarySearchTree

{

protected int Height;

// ...

}

Page 53: Árvores de Busca

53

Métodos height, getHeight e getBalanceFactor (1)

public class AVLTree extends BinarySearchTree{ protected int height;

public AVLTree() { height = -1; }

public int getHeight() { return height; }

protected void adjustHeight() {

if(isEmpty()) height = -1;

else height = 1 + Math.max (left.getHeight(),

right.getHeight()); }

Page 54: Árvores de Busca

54

Métodos height, getHeight e getBalanceFactor (2)

protected int getBalanceFactor() {

if(isEmpty()) return 0;

else return left.getHeight() - right.getHeight();

} // ...}

Page 55: Árvores de Busca

55

Método doLLRotation (1)

// pgm10_09.javapublic class AVLTree extends BinarySearchTree{ protected int Height;

protected void doLLRotation() {

if(isEmpty()) throw new InvalidOperationException();

BinaryTree tmp = right; right = left; left = right.left; right.left = right.right; right.right = tmp;

Page 56: Árvores de Busca

56

Método doLLRotation (2)

Object tmpObj = key;key = right.key;right.key = tmpObj;

getRightAVL().adjustHeight();adjustHeight();

} // ...}

Page 57: Árvores de Busca

57

Método doRRRotation (1)

public class AVLTree extends BinarySearchTree{ protected int Height;

protected void doRRRotation() {

if(isEmpty()) throw new InvalidOperationException();

BinaryTree tmp = left; left = right; right = left.right; left.right = left.left; left.left = tmp;

Page 58: Árvores de Busca

58

Método doRRRotation (2)

Object tmpObj = key;key = left.key;left.key = tmpObj;

getLeftAVL().adjustHeight();adjustHeight();

} // ...}

Page 59: Árvores de Busca

59

Método doLRRotation

// pgm10_10.javapublic class AVLTree extends BinarySearchTree{ protected int Height;

protected void doLRRotation() {

if(isEmpty()) throw new InvalidOperationException();

getLeftAVL().doRRRotation(); doLLRotation();

} // ...}

Page 60: Árvores de Busca

60

Método doRLRotation

public class AVLTree extends BinarySearchTree{ protected int Height;

protected void doRLRotation() {

if(isEmpty()) throw new InvalidOperationException();

getRightAVL().doLLRotation(); doRRRotation();

} // ...}

Page 61: Árvores de Busca

61

Método balance (1)

// pgm10_11.javapublic class AVLTree extends BinarySearchTree{ protected int Height;

protected void balance() {

adjustHeight(); if(getBalanceFactor() > 1) {

if(getLeftAVL().getBalanceFactor() > 0) doLLRotation();

else doLRRotation();

}

Page 62: Árvores de Busca

62

Método balance (2)

elseif(getBalanceFactor() < -1){

if(getRightAVL().getBalanceFactor() < 0)

doRRRotation(); else

doRLRotation();}

} // ...}

Page 63: Árvores de Busca

63

Método attachKey

// pgm10_12.javapublic class AVLTree extends BinarySearchTree{ protected int Height;

public void attachKey(Object object) {

if(!isEmpty()) throw new InvalidOperationException(); key = object; left = new AVLTree(); right = new AVLTree(); Height = 0;

} // ...}

Page 64: Árvores de Busca

Remoção de itens de Árvores AVL

Page 65: Árvores de Busca

65

Método detachKey

// pgm10_13.javapublic class AVLTree extends BinarySearchTree{ protected int Height;

public Object detachKey() {

Height = -1; return super.detachKey();

} // ...}

Page 66: Árvores de Busca

Árvores de Busca de Múltiplos caminhos

Page 67: Árvores de Busca

67

Implementação

Page 68: Árvores de Busca

68

Classe MwayTree: Métodos construtor e getM

// pgm10_14.javapublic class MWayTree extends AbstractTree implements SearchTree{ protected Comparable key[]; protected MWayTree subtree[]; public MWayTree(int m) {

if(m < 2) throw new IllegalArgumentException(“grau inválido");

key = new Comparable[m]; subtree = new MWayTree[m];

} int getM()

{ return subtree.length; } // ...}

Page 69: Árvores de Busca

69

Travessia em ordem infixa de árvores binárias de busca

Travessias infixas de árvores binárias são da forma: Percorrer a sub árvore da esquerda Visitar a raiz Percorre a sub árvore da direita

Isto corresponde a, em uma travessia infixa de uma árvore binária de busca, visitar a todos os registros armazenados na árvore em ordem

Page 70: Árvores de Busca

70

Travessia em ordem infixa

Travessias infixas não são definidas para árvores N-ariasEm árvores de busca M-Way a travessia infixa é definida como a visita a todos os registros armazenados na árvore em ordem

Page 71: Árvores de Busca

71

Travessia de um nó de uma árvore de busca M-Way

Percorrer a sub árvore T0

Visitar o objeto k1

Percorrer a sub árvore T1

Visitar o objeto k2

Percorrer a sub árvore T2

.

.

.Visitar o objeto kn-1

Percorrer a sub árvore Tn-1

Page 72: Árvores de Busca

72

Método depthFirstTraversal (1)

// pgm10_15.javapublic class MWayTree extends AbstractTree implements SearchTree{ protected Comparable key[]; protected MWayTree subtree[];

public void depthFirstTraversal (PrePostVisitor visitor) {

if(!isEmpty()) {

for(int i = 0; i <= count + 1; ++i) {

Page 73: Árvores de Busca

73

Método depthFirstTraversal (2)

if(i >= 2) visitor.postVisit(key[i - 1]);

if(i >= 1 && i <= count) visitor.inVisit(key[i]);

if(i <= count - 1) visitor.preVisit(key[i + 1]);

if(i <= count)

subtree[i].depthFirstTraversal(visitor); }

} } }

Page 74: Árvores de Busca

Busca linear de itens em Árvores M-Way

Page 75: Árvores de Busca

75

Método find (1)

// pgm10_16.javapublic class MWayTree extends AbstractTree implements SearchTree{ protected Comparable key[]; protected MWayTree subtree[];

public Comparable find(Comparable object) {

if(isEmpty()) return null;

int i;

Page 76: Árvores de Busca

76

Método find (2)

for(i = count; i > 0; --i) {

int diff = object.compare(key[i]); if(diff == 0)

return key[i]; if(diff > 0)

break; } return subtree[i].find(object);

} // ...}

Page 77: Árvores de Busca

Inclusão de itens

Page 78: Árvores de Busca

78

Método insert (1)

// pgm10_18.javapublic void insert (Comparable object){

if(isEmpty()) {

subtree[0] = new MWayTree(getM()); key[1] = object; subtree[1] = new MWayTree(getM()); count = 1; } else { int index = findIndex(object); if(index != 0 && object.isEQ(key[index]))

throw new IllegalArgumentException (“chave duplicada");

Page 79: Árvores de Busca

79

Método insert (2)

if(!isFull()) {

for(int i = count; i > index; --i) {

key[i + 1] = key[i]; subtree[i + 1] = subtree[i];

} key[index + 1] = object; subtree[index + 1] = new MWayTree(getM()); ++count;

} else

subtree[index].insert(object); }

}

Page 80: Árvores de Busca

Remoção de itens

Page 81: Árvores de Busca

81

Método withdraw (1)

public void withdraw (Comparable object){

if(isEmpty()) throw new IllegalArgumentException

("objeto não encontrado"); int index = findIndex(object); if(index != 0 && object.isEQ(key[index])) { if(!subtree[index - 1].isEmpty()) {

Comparable max = subtree[index - 1].findMax();

key[index] = max; subtree[index - 1].withdraw(max);

} else

Page 82: Árvores de Busca

82

Método withdraw (2)

if(!subtree[index].isEmpty()) {

Comparable min = subtree[index].findMin();

key[index] = min; subtree[index].withdraw(min);

} else {

--count; int i; for(i = index; i <= count; ++i) { key[i] = key[i + 1];

subtree[i] = subtree[i + 1]; }

Page 83: Árvores de Busca

83

Método withdraw (3)

key[i] = null; subtree[i] = null; if(count == 0)

subtree[0] = null; } } else subtree[index].withdraw(object);

}

Page 84: Árvores de Busca

Implementação C++

Page 85: Árvores de Busca

85

Implementação de Árvores de Busca

Page 86: Árvores de Busca

86

Definição da Classe SearchTree

// pgm10_01.cpp

class SearchTree :

public virtual Tree, public virtual SearchableContainer

{

public:

virtual Object& FindMin() const = 0;

virtual Object& FindMax() const = 0;

};

Page 87: Árvores de Busca

87

Definição da Classe BST

// pgm10_02.cpp

class BST : public BinaryTree, public SearchTree

{

protected:

virtual void AttachKey(Object&);

virtual Object& DetachKey();

virtual void Balance();

public:

BST& Left() const;

BST& Right() const;

// ...

};

Page 88: Árvores de Busca

88

Funções da Classe BinarySearchTree

leftrightfindfindMininsertattachKeywithdrawdetachKey

Page 89: Árvores de Busca

89

Definições da Função Membro Left e Rigth da Classe BST

// pgm10_03.cpp

BST& BST::Left() const

{ return dynamic_cast<BST&>(BinaryTree::Left ()); }

BST& BST::Right() const

{ return dynamic_cast<BST&>(BinaryTree::Right ()); }

Page 90: Árvores de Busca

90

Definições da Função Membro Find e FindMin da Classe BST (1)

// pgm10_04.cppObject& BST::Find(Object const& object) const{

if(IsEmpty ())return NullObject::Instance();

int const diff = object.Compare(*key);if(diff == 0)

return *key;else

if(diff < 0)return Left().Find(object);

elsereturn Right().Find(object);

}

Page 91: Árvores de Busca

91

Definições da Função Membro Find e FindMin da Classe BST (2)

Object& BST::FindMin() const{

if(IsEmpty ())return NullObject::Instance();

elseif(Left().IsEmpty())

return *key;else

return Left().FindMin();}

Page 92: Árvores de Busca

92

Inserção de itens em BST

A inclusão de nós em árvores de busca deve ser precedida de uma operação de busca. Esta operação indica se o nó buscado já existe na árvore e, em caso de não existência, o local aonde deve ser feita a inclusão. Convém lembrar que uma busca sempre termina em folha e os nós a incluir serão incluídos como filhos da folha aonde se encerrou a busca.

Page 93: Árvores de Busca

93

Definições da Função Membro Insert, AttachKey e Balance da Classe BST (1)

// pgm10 {_05.cppvoid BST::Insert(Object& object){

if(IsEmpty ())AttachKey(object);

elseint const diff = object.Compare(*key);if(diff == 0)

throw invalid_argument(“chave duplicada");

if(diff < 0)Left().Insert(object);

elseRight().Insert(object);

}Balance();

}

Page 94: Árvores de Busca

94

Definições da Função Membro Insert, AttachKey e Balance da Classe BST (2)

void BST::AttachKey(Object& object){

if(!IsEmpty ())throw domain_error("operação inválida");

key = &object;left = new BST();right = new BST();

}void BST::Balance()

{}

Page 95: Árvores de Busca

95

Remoção de itens em BST

A exclusão de nós em árvores de busca pode configurar um de 3 casos. Se o nó não tiver filhos pode ser excluído sem exigir

ajustamento da árvore. Se o nó a excluir tiver apenas uma sub árvore, este nó

pode ser excluído e deve ser substituído por seu filho único.

Se o nó a excluir tiver mais de um filho, para que ele possa ser excluído, deve ser substituído por seu antecessor ou seu sucessor em ordem infixa. O nó substituto deve ser excluído da sua posição gerando outro processo de exclusão.

Considerando o caso do sucessor em ordem infixa, o nó a ser excluído deve ser substituído pelo nó obtido alcançando-se o nó mais à esquerda da sub árvore direita do nó a excluir.

Page 96: Árvores de Busca

96

Remoção de itens em BST

Remoção do nó (4) folha em BST

Remoção do nó (1) não folha em BST

Page 97: Árvores de Busca

97

Definições da Função Membro Withdraw e DetachKey da Classe BST (1)

// pgm10_06.cppvoid BST::Withdraw(Object& object){

if(IsEmpty ())throw invalid_argument("objeto não

encontrado");int const diff = object.Compare(*key);if(diff == 0){

if(!Left().IsEmpty()){

Object& max = Left().FindMax();key = &max;Left().Withdraw(max);

}

Page 98: Árvores de Busca

98

Definições da Função Membro Withdraw e DetachKey da Classe BST (2)

elseif(!Right().IsEmpty()){Object& min = Right().FindMin();key = &min;Right().Withdraw(min);}elseDetachKey();}elseif(diff < 0)Left().Withdraw(object);elseRight().Withdraw(object);Balance();

}

Page 99: Árvores de Busca

99

Definições da Função Membro Withdraw e DetachKey da Classe BST (3)

Object& BST::DetachKey(){

if(!IsLeaf ())throw domain_error("operação inválida");

Object& result = *key;delete left;delete right;key = 0;left = 0;right = 0;return result;

}

Page 100: Árvores de Busca

Implementação de árvores AVL

Page 101: Árvores de Busca

101

Conceito de AVL

Adelson-Velskii e Landis propuseram as condições de balanceamento para uma árvore binária que recebeu como sigla suas iniciais.

Definição (Condição de equilíbrio AVL)  Uma árvore binária vazia é AVL balanceada  . Uma árvore binária não-vazia, T={r,TL,TR} , é AVL balanceada se tanto TL quanto TR forem AVL balanceadas e |hL-hR|<=1

aonde hL é a altura of TL e hR é a altura of TR .

Page 102: Árvores de Busca

Implementação de árvores AVL

Page 103: Árvores de Busca

103

Definição da Classe AVLTree (1)

// pgm10_07.cppclass AVLTree : public BST{protected:

int height;int BalanceFactor() const;void AdjustHeight();void LLRotation();void LRRotation();void RRRotation();void RLRotation();void AttachKey(Object&);Object& DetachKey();void Balance();

Page 104: Árvores de Busca

104

Definição da Classe AVLTree (2)

public:

AVLTree();

int Height() const;

AVLTree& Left() const;

AVLTree& Right() const;

};

Page 105: Árvores de Busca

105

Definições da Função Membro Height, AdjustHeight e BalanceFactor e do Construtor da Classe AVLTree (1)

// pgm10_08.cppAVLTree::AVLTree() :

BST(),height(-1){}

int AVLTree::Height() const{ return height; }

void AVLTree::AdjustHeight(){

if(IsEmpty ())height = -1;

elseheight = Max(left->Height(), right->Height())

+ 1;}

Page 106: Árvores de Busca

106

Definições da Função Membro Height, AdjustHeight e BalanceFactor e do Construtor da Classe AVLTree (2)

int AVLTree::BalanceFactor() const

{

if(IsEmpty ())

return 0;

else

return left->Height() - right->Height();

}

Page 107: Árvores de Busca

107

Definição da Função Membro LLRotation da Classe AVLTree// pgm10_09.cppvoid AVLTree::LLRotation(){

if(IsEmpty ())throw domain_error(“rotação inválida");

BinaryTree* const tmp = right;right = left;left = Right().left;Right().left = Right().right;Right().right = tmp;Object* const tmpObj = key;key = Right().key;Right().key = tmpObj;Right().AdjustHeight();AdjustHeight();

}

Page 108: Árvores de Busca

108

Definição da Função Membro LRRotation da Classe AVLTree

// pgm10_10.cpp

void AVLTree::LRRotation()

{

if(IsEmpty ())

throw domain_error("rotação inválida");Left().RRRotation();

LLRotation();

}

Page 109: Árvores de Busca

109

Definição da Função Membro Balance da Classe AVLTree

// pgm10_11.cppvoid AVLTree::Balance() {

AdjustHeight();if(abs(BalanceFactor ()) > 1) {

if(BalanceFactor() > 0) {if(Left().BalanceFactor() > 0)

LLRotation();else

LRRotation();}else {

if(Right().BalanceFactor() < 0)RRRotation();

elseRLRotation();

}}

}

Page 110: Árvores de Busca

110

Definições das Função Membro AttachKey e DetachKey da Classe AVLTree

// pgm10_12.cpp

void AVLTree::AttachKey(Object& object)

{

if(!IsEmpty ())

throw domain_error("operação inválida");

key = &object;

left = new AVLTree();

right = new AVLTree();

height = 0;

}

Object& AVLTree::DetachKey()

{ height = -1; return BST::DetachKey (); }

Page 111: Árvores de Busca

111

Definição da Classe MWayTree

// pgm10_13.cppclass MWayTree : public SearchTree{protected:

unsigned int const m;unsigned int numberOfKeys;Array<Object*> key;Array<MWayTree*> subtree;unsigned int FindIndex(Object const&) const;

public:MWayTree(unsigned int);~MWayTree();Object& Key(unsigned int) const;MWayTree& Subtree(unsigned int) const;// ...

};

Page 112: Árvores de Busca

112

Definição da Função Membro DepthFirstTraversal da Classe MWayTree

// pgm10_14.cppvoid MWayTree::DepthFirstTraversal( PrePostVisitor& visitor) const{

if(!IsEmpty ()){

for(int i = 0; i <= numberOfKeys + 1; ++i){

if(i >= 2)visitor.PostVisit(*key [i - 1]);

if(i >= 1 && i <= numberOfKeys)visitor.Visit(*key [i]);

if(i <= numberOfKeys - 1)visitor.PreVisit(*key [i + 1]);

if(i <= count)subtree[i]->DepthFirstTraversal (visitor);

}}

}

Page 113: Árvores de Busca

113

Definição (Linear Search) da Função Membro Find da Classe MWayTree// pgm10_15.cppObject& MWayTree::Find(Object const& object) const{

if(IsEmpty ())return NullObject::Instance();

unsigned int i = numberOfKeys;while(i > 0){

int const diff = object.Compare(*key[i]);if(diff == 0)

return *key[i];if(diff > 0)

break;--i;

}return subtree[i]->Find(object);

}

Page 114: Árvores de Busca

114

Definições (Binary Search) da Função FindIndex e Find da Classe MWayTree (1)

// pgm10_16.cppunsigned int MWayTree::FindIndex(Object const& object) const{

if(IsEmpty ())throw domain_error("operação inválida");

if(object < *key[1])return 0;

unsigned int left = 1;unsigned int right = numberOfKeys;while(left < right) {

int const middle = (left + right + 1) / 2;if(object >= *key[middle])

left = middle;else

right = middle - 1U;}return left;

}

Page 115: Árvores de Busca

115

Definições (Binary Search) da Função FindIndex e Find da Classe MWayTree (2)

Object& MWayTree::Find(Object const& object) const{

if(IsEmpty ())return NullObject::Instance();

unsigned int const index = FindIndex(object);if(index != 0 && object == *key[index])

return *key[index];else

return subtree[index]->Find(object);}

Page 116: Árvores de Busca

116

Definição da Função Membro Insert da Classe MWayTree (1)

// pgm10_17.cppvoid MWayTree::Insert(Object& object){

if(IsEmpty ()){

subtree[0] = new MWayTree(m);key[1] = &object;subtree[1] = new MWayTree(m);numberOfKeys = 1;

}else{

unsigned int const index = FindIndex(object);if(index != 0 && object == *key[index])

throw invalid_argument(“chave duplicada");

if(numberOfKeys < m - 1U){

Page 117: Árvores de Busca

117

Definição da Função Membro Insert da Classe MWayTree (2)

for(unsigned int i = numberOfKeys; i > index; --i)

{

key[i + 1] = key[i];

subtree[i + 1] = subtree[i];

}

key[index + 1] = &object;

subtree[index + 1] = new MWayTree(m);

++numberOfKeys;

}

else

subtree[index]->Insert(object);

}

}

Page 118: Árvores de Busca

118

Definição da Função Membro Withdraw da Classe MWayTree (1)

// pgm10_18.cppvoid MWayTree::Withdraw(Object& object){

if(IsEmpty ())throw invalid_argument("objeto não encontrado");

unsigned int const index = FindIndex(object);if(index != 0 && object == *key[index]){

if(!subtree[index - 1U]->IsEmpty()){

Object& max = subtree[index - 1U]->FindMax();

key[index] = &max;subtree[index - 1U]->Withdraw(max);

}

Page 119: Árvores de Busca

119

Definição da Função Membro Withdraw da Classe MWayTree (2)

elseif(!subtree[index]->IsEmpty()){

Object& min = subtree[index]->FindMin();key[index] = &min;subtree[index]->Withdraw(min);

}else{

--numberOfKeys;delete subtree[index];for(unsigned int i = index; i <= numberOfKeys; ++i){

key[i] = key[i + 1];subtree[i] = subtree[i + 1];

}

Page 120: Árvores de Busca

120

Definição da Função Membro Withdraw da Classe MWayTree (3)

if(numberOfKeys == 0)delete subtree[0];

}}else subtree[index]->Withdraw(object);

}

Page 121: Árvores de Busca

121

Definição da Classe BTree

// pgm10_19.cppclass BTree : public MWayTree{

BTree* parent;void InsertPair(Object&, BTree&);void AttachKey(unsigned int, Object&);void AttachSubtree(unsigned int, MWayTree&);Object& InsertKey(unsigned int, Object&);BTree& InsertSubtree(unsigned int, BTree&);void AttachLeftHalfOf(BTree const&);void AttachRightHalfOf(BTree const&, Object&, BTree&);

public:BTree(unsigned int);BTree(unsigned int, BTree&);void Insert(Object&);void Withdraw(Object&);

};

Page 122: Árvores de Busca

122

Definição da Função Membro Insert da Classe BTree (1)

// pgm10_20.cppvoid BTree::Insert(Object& object){

if(IsEmpty ()){

if(parent == 0){

AttachSubtree(0, *new BTree(m, *this));AttachKey(1, object);AttachSubtree(1, *new BTree(m, *this));numberOfKeys = 1;

}else

parent->InsertPair(object, *new BTree(m, *parent));}

Page 123: Árvores de Busca

123

Definição da Função Membro Insert da Classe BTree (2)

else{

unsigned int const index = FindIndex(object);if(index != 0 && object == *key[index]) throw invalid_argument(“chave duplicada");subtree[index]->Insert(object);

}}

Page 124: Árvores de Busca

124

Definição da Função Membro InsertPair da Classe BTree (1)

// pgm10_21.cppvoid BTree::InsertPair(Object& object, BTree& child){

unsigned int const index = FindIndex(object);BTree& extraTree = InsertSubtree(index + 1, child);Object& extraKey = InsertKey(index + 1, object);if(++numberOfKeys == m){

if(parent == 0){

BTree& left = *new BTree(m, *this);BTree& right = *new BTree(m, *this);left.AttachLeftHalfOf(*this);

Page 125: Árvores de Busca

125

Definição da Função Membro InsertPair da Classe BTree (2)

right.AttachRightHalfOf(*this, extraKey, extraTree);

AttachSubtree(0, left);AttachKey(1, *key[(m + 1)/2]);AttachSubtree(1, right);numberOfKeys = 1;

}else{

numberOfKeys =(m + 1) / 2 - 1;BTree& right = *new BTree(m, *parent);right.AttachRightHalfOf(*this, extraKey,

extraTree);parent->InsertPair(*key[(m + 1)/2], right);

}}

}