107
Árvores B Implementação pelos FrameWork Bruno Preiss

Árvores B Implementação pelos FrameWork Bruno Preiss

Embed Size (px)

Citation preview

Page 1: Árvores B Implementação pelos FrameWork Bruno Preiss

Árvores B

Implementação pelos FrameWork Bruno Preiss

Page 2: Árvores B Implementação pelos FrameWork Bruno Preiss

Árvores B

FrameWork Java de Bruno Preiss

Page 3: Árvores B Implementação pelos FrameWork Bruno Preiss

3

Framework de Árvores e Busca

Page 4: Árvores B Implementação pelos FrameWork Bruno Preiss

4

Interface Comparable

//pgm05_01.txtpublic interface Comparable{ boolean isLT (Comparable object); boolean isLE (Comparable object); boolean isGT (Comparable object); boolean isGE (Comparable object); boolean isEQ (Comparable object); boolean isNE (Comparable object); int compare (Comparable object);}

Page 5: Árvores B Implementação pelos FrameWork Bruno Preiss

5

Declaração da classe AbstractObject// pgm05_02.txtpublic abstract class AbstractObject implements Comparable{ public final boolean isLT (Comparable object)

{ return compare (object) < 0; }  public final boolean isLE (Comparable object)

{ return compare (object) <= 0; }  public final boolean isGT (Comparable object)

{ return compare (object) > 0; }  public final boolean isGE (Comparable object)

{ return compare (object) >= 0; }  public final boolean isEQ (Comparable object)

{ return compare (object) == 0; }  public final boolean isNE (Comparable object)

{ return compare (object) != 0; }  public final boolean equals (Object object) {

if (object instanceof Comparable) return isEQ ((Comparable) object);else return false;

}

Page 6: Árvores B Implementação pelos FrameWork Bruno Preiss

6

Métodos compareTo e compare da classe AbstractObject

//pgm05_03.txt//public abstract class AbstractObject implements Comparable{ protected abstract int compareTo (Comparable arg);  public final int compare (Comparable arg) {

if (getClass () == arg.getClass ()) return compareTo (arg);else return getClass ().getName ().compareTo (

arg.getClass ().getName ()); } // ...}

Page 7: Árvores B Implementação pelos FrameWork Bruno Preiss

7

Interface Container

public interface Container extends Comparable{ int getCount (); boolean isEmpty (); boolean isFull (); void purge (); void accept (Visitor visitor); Enumeration getEnumeration ();}

Page 8: Árvores B Implementação pelos FrameWork Bruno Preiss

8

Interface SearchableContainer

public interface SearchableContainer extends Container{ boolean isMember (Comparable object); void insert (Comparable object); void withdraw (Comparable obj); Comparable find (Comparable object);}

Page 9: Árvores B Implementação pelos FrameWork Bruno Preiss

9

Interface Tree

//pgm09_01.txtpublic interface Tree extends Container{ Object getKey (); Tree getSubtree (int i); boolean isEmpty (); boolean isLeaf (); int getDegree (); int getHeight (); void depthFirstTraversal (PrePostVisitor visitor); void breadthFirstTraversal (Visitor visitor);}

Page 10: Árvores B Implementação pelos FrameWork Bruno Preiss

10

Interface SearchTree

//pgm10_01.txtpublic interface SearchTree extends Tree, SearchableContainer

{ Comparable findMin (); Comparable findMax ();}

Page 11: Árvores B Implementação pelos FrameWork Bruno Preiss

11

Classe Abstrata AbstractContainer

public abstract class AbstractContainer extends AbstractObject implements Container{ protected int count; public int getCount (){ return count; }

public boolean isEmpty (){ return getCount () == 0; }

public boolean isFull (){ return false; }

// ...}

Page 12: Árvores B Implementação pelos FrameWork Bruno Preiss

12

Classe Abstrata AbstractTree

// pgm09_02.txtpublic abstract class AbstractTree extends AbstractContainer implements Tree{ public void depthFirstTraversal (PrePostVisitor visitor) {

if (visitor.isDone ()) return;if (!isEmpty ()){ visitor.preVisit (getKey ()); for (int i = 0; i < getDegree (); ++i)

getSubtree (i).depthFirstTraversal (visitor); visitor.postVisit (getKey ());}

} // ...}

Page 13: Árvores B Implementação pelos FrameWork Bruno Preiss

13

Árvores MWay

Page 14: Árvores B Implementação pelos FrameWork Bruno Preiss

14

Classe MwayTree: Métodos construtor e getM

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

public MWayTree (int m) {

if (m < 2) throw new IllegalArgumentException("invalid degree");key = new Comparable [m];subtree = new MWayTree [m];

}

int getM (){ return subtree.length; }

// ...}

Page 15: Árvores B Implementação pelos FrameWork Bruno Preiss

15

Método find

Recebe um objeto e localiza o item na árvore de busca que coincide com o objeto buscado

Caso o objeto buscado não exista retorna null

Page 16: Árvores B Implementação pelos FrameWork Bruno Preiss

16

Método find da Classe MWayTree//pgm10_16.txtpublic class MWayTree extends AbstractTree implements SearchTree{ protected Comparable key[]; protected MWayTree subtree[];

public Comparable find (Comparable object) {

if (isEmpty ()) return null;int i;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 17: Árvores B Implementação pelos FrameWork Bruno Preiss

17

Método findIndex

Recebe um objeto x e retorna i que é o maior valor tal que x ≥ ki, sendo ki a chave de ordem i no nó

Page 18: Árvores B Implementação pelos FrameWork Bruno Preiss

18

Método findIndex da Classe MWayTree//pgm10_17.txtpublic class MWayTree extends AbstractTree implements SearchTree{ protected Comparable key[]; protected MWayTree subtree[];

protected int findIndex (Comparable object) {

if (isEmpty () || object.isLT (key [1])) return 0;int left = 1;int right = count;while (left < right){ int middle = (left + right + 1) / 2; if (object.isLT (key [middle]))

right = middle - 1; else

left = middle;}return left;

}

Page 19: Árvores B Implementação pelos FrameWork Bruno Preiss

19

Classe BTree

// pgm10_20.txtpublic class BTree extends MWayTree{ protected BTree parent;

public BTree (int m){ super (m); }

public void attachSubtree (int i, MWayTree arg) {

BTree btree = (BTree) arg;subtree [i] = btree;btree.parent = this;

} // ...}

Page 20: Árvores B Implementação pelos FrameWork Bruno Preiss

20

Método insert da Classe BTree

Insere uma chave em uma página de árvore BSe a página está vazia então: Se a página não tem ancestral a chave será key[1] e a

página passará a ter duas filhas vazias Caso contrário inserir no ancestral o par (chave, árvore B

vazia) pelo método insertPairSe a página não estiver vazia: Faz-se a busca do local apropriado calculando index pelo

método findIndex Se o objeto for encontrado é lançada a exceção de chave

duplicada O método chama a si mesmo recursivamente da forma

subtree [index].insert (object)

Page 21: Árvores B Implementação pelos FrameWork Bruno Preiss

21

Método insert da Classe BTree// pgm10_21.txt public void insert (Comparable object) {

if (isEmpty ()){ if (parent == null) {attachSubtree (0, new BTree (getM ()));key [1] = object;attachSubtree (1, new BTree (getM ()));count = 1; } elseparent.insertPair (object, new BTree (getM ()));}else{ int index = findIndex (object); if (index != 0 && object.isEQ (key [index]))throw new IllegalArgumentException ( "duplicate key"); subtree [index].insert (object);}

}

Page 22: Árvores B Implementação pelos FrameWork Bruno Preiss

22

Método insertPair da Clase BTree (1)

Inclui em um nó de árvore B um par (object, child)

Inicia buscando a posição correta na página com findIndex

Caso a página não esteja cheia: O método insertKey é chamado para inserir a chave (object) na posição

correta do array de chaves O método insertSubtree é chamado para inserir a árvore (child) na

correta posição do array de sub árvores

Caso a página esteja cheia: O método insertKey retorna a chave que transborda do array de chaves

(maior valor) e que é atribuída a extraKey O método insertSubtree retorna a sub árvore que sobra à direita do

array de sub árvores e que é atribuída a extraTree

Page 23: Árvores B Implementação pelos FrameWork Bruno Preiss

23

Método insertPair da Clase BTree (2)

A página transbordou e é preciso balancear a árvoreSe o nó for a raiz: Criam-se dois nós left e right Left recebe as primeiras chaves e primeiras

sub árvores pelo método attachLeftHalfOf Right recebe as últimas chaves a as últimas

sub árvores pelo método attachRightHalfOf O par (extraKey,extraTree) é incluído no nó right Left será a sub árvore 0 ligada à raiz por AttachSubtree Right será a sub árvore 1 ligada à raiz por AttachSubtree A chave que sobrou, , é inserida na raiz modificada que terá

por folhas as página left e right

Page 24: Árvores B Implementação pelos FrameWork Bruno Preiss

24

Método insertPair da Clase BTree (3)

Se o nó não for a raiz: Cria-se um novo nó e right Right recebe as últimas chaves a as últimas

sub árvores pelo método attachRightHalfOf O par (extraKey,extraTree) é incluído no nó right As primeiras chaves e primeiras sub árvores permanecem no

nó corrente A chave que sobrou é O método chama a si mesmo, recursivamente, para inserir no

ancestral o par (chave que sobrou, right)

Page 25: Árvores B Implementação pelos FrameWork Bruno Preiss

25

Método insertPair da Clase Btree (1)

protected void insertPair (Comparable object, BTree child) {

int index = findIndex (object);if (!isFull ()){ insertKey (index + 1, object); insertSubtree (index + 1, child); ++count;}else{ Comparable extraKey = insertKey (index + 1, object); BTree extraTree = insertSubtree (index + 1, child); if (parent == null) {

BTree left = new BTree (getM ());BTree right = new BTree (getM ());left.attachLeftHalfOf (this);right.attachRightHalfOf (this);right.insertPair (extraKey, extraTree);attachSubtree (0, left);key [1] = key [(getM () + 1)/2];attachSubtree (1, right);count = 1;

}

Page 26: Árvores B Implementação pelos FrameWork Bruno Preiss

26

Método insertPair da Clase Btree (2)

else {

count = (getM () + 1)/2 - 1;BTree right = new BTree (getM ());right.attachRightHalfOf (this);right.insertPair (extraKey, extraTree);parent.insertPair (key [(getM () + 1)/2], right);

}}

}

Page 27: Árvores B Implementação pelos FrameWork Bruno Preiss

27

Método attachSubtree

Recebe um inteiro i e uma árvore B

A árvore B recebida torna-se a sub árvore de ordem i do nó corrente

Page 28: Árvores B Implementação pelos FrameWork Bruno Preiss

28

Método attachSubtree

public void attachSubtree

(int i, MWayTree arg)

{

BTree btree = (BTree) arg;

subtree [i] = btree;

btree.parent = this;

}

Page 29: Árvores B Implementação pelos FrameWork Bruno Preiss

29

Metodo attachLeftHalfOf

protected void attachLeftHalfOf (BTree tree) throws IllegalArgumentException

{ attachSubtree (0, tree.subtree [0]); count = 0; for (int ind = 1; ind < Math.ceil (((float) tree.getM ()) / 2); ++ind) { this.insertPair (tree.key [ind], (BTree) tree.subtree [ind]); } }

Page 30: Árvores B Implementação pelos FrameWork Bruno Preiss

30

Metodo attachRightHalfOf

protected void attachRightHalfOf (BTree tree) throws IllegalArgumentException

{ attachSubtree (0, tree.subtree [(getM () + 1) / 2]);

count = 0; for (int ind = getM () - 1; ind > Math.ceil ((tree.getM () + 1) / 2); --ind) { this.insertPair (tree.key [ind], (BTree) tree.subtree [ind]);

} }

Page 31: Árvores B Implementação pelos FrameWork Bruno Preiss

31

Método insertSubtree

Recebe um inteiro índice e uma sub árvore e deve inserir na correta posição do array de sub árvoresCaso a página não esteja cheia: A inserção é feita usando AttachSubtree e o

método retorna null As sub árvores “acima” do índice são rearrumadas

Caso a página esteja cheia: O método insertSubtree retorna a sub árvore que sobra à

direita do array de sub árvores e que é atribuída a extraTree

Page 32: Árvores B Implementação pelos FrameWork Bruno Preiss

32

Método insertSubtree (1)

private BTree insertSubtree (int index, BTree child) { BTree extraTree = null; if (isFull ()) { if (index == getM ()) extraTree = child; else { extraTree = (BTree) subtree [count];

for (int i = count - 1; i >= index; --i) { subtree [i + 1] = subtree [i]; } attachSubtree (index, child); } }

Page 33: Árvores B Implementação pelos FrameWork Bruno Preiss

33

Método insertSubtree (2)

else { child.parent = this; for (int i = count; i >= index; --i) { subtree [i + 1] = subtree [i]; } subtree [index] = child; } return extraTree; }

Page 34: Árvores B Implementação pelos FrameWork Bruno Preiss

34

Método insertKey

Recebe um inteiro índice e um objeto e deve inserir na correta posição do array de chaves

Caso a página não esteja cheia: A inserção é feita e o método retorna null As chaves “acima” do índice são rearrumadas

Caso a página esteja cheia: O método insertKey retorna a chave que transborda do

array (maior valor) e que é atribuída a extraKey

Page 35: Árvores B Implementação pelos FrameWork Bruno Preiss

35

Método insertKey (1)

private Comparable insertKey (int index, Comparable object) { Comparable extraKey = null; if (isFull ()) { if (index == getM ()) extraKey = object; else { extraKey = key [count]; for (int i = count - 1; i >= index; --i) { key [i + 1] = key [i]; } key [index] = object; } }

Page 36: Árvores B Implementação pelos FrameWork Bruno Preiss

36

Método insertKey (2)

else { for (int i = count; i >= index; --i) { key [i + 1] = key [i]; } // for (int i = count; i > index; --i) {

key [index] = object; } return extraKey; }

Page 37: Árvores B Implementação pelos FrameWork Bruno Preiss

37

Método withdraw (1)

Remove um objeto da árvore

Se a árvore estiver vazia lança uma exceção

Determina a posição do objeto no nó pelo método findIndex

Caso tenha encontrado o objeto a excluir em uma página não folha procura seu antecessor ou sucessor para gravar sobre o objeto a ser excluído e trata de excluir o antecessor ou sucessor

Page 38: Árvores B Implementação pelos FrameWork Bruno Preiss

38

Método withdraw (2)

Caso tenha encontrado o objeto a excluir em folha: Decrementa o contador de população Leva para a esquerda do array de objetos todos os

superiores ao index do objeto a excluir Leva para a esquerda do array de sub árvores todas

as sub árvores correspondentes Anula o objeto e a sub árvore a excluir

Page 39: Árvores B Implementação pelos FrameWork Bruno Preiss

39

Método withdraw (3)

Caso não tenha encontrado o objeto a excluir por estar entre dois objetos do nó chama a si mesmo da forma

subtree[index].withdraw(object)

Se o contador tornar-se menor do que o mínimo: Se a nó corrente tiver ancestral chama o método

balance Se for raiz e tiver ficado vazia chama o método

TrimmRoot

Page 40: Árvores B Implementação pelos FrameWork Bruno Preiss

40

Método withdraw (1)public void withdraw (Comparable object) throws IllegalArgumentException, InvalidOperationException { if (isEmpty ()) throw new IllegalArgumentException ("object not found"); 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 if (!subtree [index].isEmpty ()) { Comparable min = subtree [index].findMin (); key [index] = min; subtree [index].withdraw (min); }

Page 41: Árvores B Implementação pelos FrameWork Bruno Preiss

41

Método withdraw (2)else { --count; int i; for (i = index; i <= count; ++i) { key [i] = key [i + 1]; subtree [i] = subtree [i + 1]; } key [i] = null; subtree [i] = null; } } else subtree [index].withdraw (object);

if (count < getMin ()) if (parent != null) balance (); else if (count == 0) rootTrim (); }

Page 42: Árvores B Implementação pelos FrameWork Bruno Preiss

42

Métodos getMin e isFull

public int getMin ()

{

return ((getM () + 1) / 2) - 1;

}

public boolean isFull ()

{

return getM () - 1 == count;

}

Page 43: Árvores B Implementação pelos FrameWork Bruno Preiss

43

Método balanceEquilibra uma página sub povoadaDetermina a posição no paiObtém a população das irmãs esquerda e direitaCaso a população da esquerda seja maior do que o mínimo executa uma rotação à esquerdaSenão se a população da direita for maior do que o mínimo executa uma rotação à direitaCaso contrário todas as páginas envolvidas estão com população mínima e então: concatena com a esquerda

(parent.concatenation(parentIndex)) ou concatena com a direita

(parent.concatenation(parentIndex + 1))

Existe um teste de lado pois existe o tratamento diferenciado das páginas extremas que possuem irmãs fictícias com população menor do que a população mínima

Page 44: Árvores B Implementação pelos FrameWork Bruno Preiss

44

Método balancepublic void balance () throws IllegalArgumentException, InvalidOperationException { int parentIndex = parent.findIndex (this.key [1]);

int LeftSister = getCountLeftSister (parentIndex); int RightSister = getCountRightSister (parentIndex);

if (LeftSister > getMin ()) { parent.doLLRotation (parentIndex); }

else if (RightSister > getMin ()) { parent.doRRRotation (parentIndex); }

else if (LeftSister >= RightSister) { parent.concatenation (parentIndex); } else { parent.concatenation (parentIndex + 1); } }

Page 45: Árvores B Implementação pelos FrameWork Bruno Preiss

45

Método printTreepublic void printTree (Visitor visitor, int espaços) throws ContainerEmptyException { if (!isEmpty ()) { for (int i = count + 1; i >= 0; --i) { if (i <= count) { ((BTree) subtree [i]).printTree (visitor, espaços + 3); }

if (i >= 1 && i <= count) { for (int o = espaços; o > 0; --o) System.out.print (" "); visitor.visit (key [i]); } } } else if (parent == null) throw new ContainerEmptyException ("Arvore vazia!"); }

Page 46: Árvores B Implementação pelos FrameWork Bruno Preiss

46

Método getCountLeftSister

Obtém a população da irmã esquerda

Se for a primeira página sua irmã da esquerda (inexistente) recebe população menor do que o mínimo

Caso contrário usa-se o método getCountparent.subtree[index - 1].getCount()

Page 47: Árvores B Implementação pelos FrameWork Bruno Preiss

47

Método getCountLeftSister

public int getCountLeftSister (int index) { if (index == 0) return getMin () - 1; else return parent.subtree [index - 1].getCount (); }

Page 48: Árvores B Implementação pelos FrameWork Bruno Preiss

48

Método getCountRightSister

Obtém a população da irmã direita

Se for a última página sua irmã da direita (inexistente) recebe população menor do que o mínimo

Caso contrário usa-se o método getCountparent.subtree[index + 1].getCount()

Page 49: Árvores B Implementação pelos FrameWork Bruno Preiss

49

Método getCountRightSister

public int getCountRightSister (int index) { if (index == this.parent.count) return getMin () - 1; else return parent.subtree [index + 1].getCount (); }

Page 50: Árvores B Implementação pelos FrameWork Bruno Preiss

50

Método doLLRotation

Determina a posição do último objeto da irmã esquerda e a sub árvore correspondente No nó corrente pelo método insertPair são gravados key[index] e a sub árvore determinada no item anteriorkey[index] recebe o último objeto da irmã esquerdaO último objeto da irmã esquerda e a sub árvore correspondente são removidos pelo método removePair

Page 51: Árvores B Implementação pelos FrameWork Bruno Preiss

51

Método doLLRotationprotected void doLLRotation (int index) throws InvalidOperationException, IllegalArgumentException { if (isEmpty ()) throw new InvalidOperationException ("Operação inválida!");

Comparable tempKey; BTree tempSubtree; int ultimaPosiçao;

ultimaPosiçao = subtree [index - 1].getCount ();

tempKey = subtree [index - 1].key [ultimaPosiçao]; tempSubtree = (BTree) subtree [index - 1].subtree [ultimaPosiçao];

((BTree) subtree [index]).insertPair (key [index], tempSubtree);

key [index] = tempKey;

((BTree) subtree [index - 1]).removePair (ultimaPosiçao); }

Page 52: Árvores B Implementação pelos FrameWork Bruno Preiss

52

Método doRRRotation

Determina a posição do primeiro objeto da irmã direita e a sub árvore correspondente No nó corrente pelo método insertPair são gravados key[index + 1] e a sub árvore determinada no item anteriorkey[index + 1] recebe o primeiro objeto da irmã direitaO primeiro objeto da irmã direita e a sub árvore correspondente são removidos pelo método removePair

Page 53: Árvores B Implementação pelos FrameWork Bruno Preiss

53

Método doRRRotationprotected void doRRRotation (int index) throws

InvalidOperationException, IllegalArgumentException { if (isEmpty ()) throw new InvalidOperationException ("Operação inválida!");

BTree tempSubtree;

tempSubtree = (BTree) subtree [index + 1].subtree [0];

((BTree) subtree [index]).insertPair (key [index + 1], tempSubtree);

key [index + 1] = subtree [index + 1].key [1];

subtree [index + 1].subtree [0] = subtree [index + 1].subtree [1]; ((BTree) subtree [index + 1]).removePair (1); }

Page 54: Árvores B Implementação pelos FrameWork Bruno Preiss

54

Método concatenationConcatena a página filha corrente (que será desalocada) com sua irmã esquerdaA chave separadora de nós (key [index]) e a sub árvore da esquerda da página filha corrente são copiados para a irmã esquerda pelo método insertPairTodas as chaves e sub árvores correspondentes da página filha corrente são copiados para a irmã esquerda pelo método insertPairTodas as chaves e sub árvores da página corrente (ancestral das que sofreram concatenação) maiores do que key [index], que perdeu levado para a filha esquerda, são deslocados para a esquerdaA última chave e a última sub árvore da página corrente são anuladas

Page 55: Árvores B Implementação pelos FrameWork Bruno Preiss

55

Método concatenationprotected void concatenation (int index) throws IllegalArgumentException { ((BTree) subtree [index - 1]).insertPair (key [index], (BTree) subtree [index].subtree [0]);

for (int i = 1; i <= subtree [index].getCount (); ++i) { ((BTree) subtree [index - 1]).insertPair (subtree [index].key [i], BTree) subtree [index].subtree [i]); }

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

Page 56: Árvores B Implementação pelos FrameWork Bruno Preiss

56

Método rootTrimprotected void rootTrim () { count = subtree [0].getCount ();

int i; for (i = count; i > 0; --i) { key [i] = subtree [0].key [i]; subtree [i] = subtree [0].subtree [i]; ((BTree) subtree [i]).parent = this; } subtree [i] = subtree [0].subtree [i]; ((BTree) subtree [i]).parent = this; }

Page 57: Árvores B Implementação pelos FrameWork Bruno Preiss

57

Método removePair

Remove de uma página a chave key [index] e a sub árvore correspondenteO contador de objetos é decrementadoTodas as chaves e sub árvores da página corrente maiores do que key [index], que perdeu levado para a filha esquerda, são deslocados para a esquerdaA última chave e a última sub árvore da página corrente são anuladas

Page 58: Árvores B Implementação pelos FrameWork Bruno Preiss

58

Método removePair

public void removePair (int index) { int i; --count; for (i = index; i <= count; ++i) { key [i] = key [i + 1]; subtree [i] = subtree [i + 1]; }

key [i] = null; subtree [i] = null; }

Page 59: Árvores B Implementação pelos FrameWork Bruno Preiss

Árvores B

FrameWork C++ de Bruno Preiss

Page 60: Árvores B Implementação pelos FrameWork Bruno Preiss

60

Framework de Árvores e Busca

Page 61: Árvores B Implementação pelos FrameWork Bruno Preiss

61

Árvores MWay

Page 62: Árvores B Implementação pelos FrameWork Bruno Preiss

62

Declaração da Classe Object

// pgm05_01.cppclass Object{protected: virtual int CompareTo (Object const&) const = 0;public: virtual ~Object (); virtual bool IsNull () const; virtual int Compare (Object const&) const; virtual HashValue Hash () const = 0; virtual void Put (ostream&) const = 0;};

Page 63: Árvores B Implementação pelos FrameWork Bruno Preiss

63

Declaração da Classe Container// pgm05_09.cppclass Container : public virtual Object, public virtual Ownership{protected: unsigned int count;

Container ();public: virtual unsigned int Count () const; virtual bool IsEmpty () const; virtual bool IsFull () const; virtual HashValue Hash () const; virtual void Put (ostream&) const; virtual Iterator& NewIterator () const;

virtual void Purge () = 0; virtual void Accept (Visitor&) const = 0;};

Page 64: Árvores B Implementação pelos FrameWork Bruno Preiss

64

Declaração da Classe Ownership

// pgm05_17.cppclass Ownership{ bool isOwner;protected: Ownership () : isOwner (true)

{} Ownership (Ownership& arg) : isOwner (arg.isOwner)

{ arg.isOwner = false; }public: void AssertOwnership ()

{ isOwner = true; } void RescindOwnership ()

{ isOwner = false; } bool IsOwner () const

{ return isOwner; }};

Page 65: Árvores B Implementação pelos FrameWork Bruno Preiss

65

Declaração da Classe SearchableContainer

// pgm05_21.cppclass SearchableContainer : public virtual Container

{public: virtual bool IsMember (Object const&) const = 0;

virtual void Insert (Object&) = 0; virtual void Withdraw (Object&) = 0; virtual Object& Find (Object const&) const = 0;

};

Page 66: Árvores B Implementação pelos FrameWork Bruno Preiss

66

Declaração da Classe Tree

// pgm09_01.cppclass Tree : public virtual Container{ class Iter;public: virtual Object& Key () const = 0; virtual Tree& Subtree (unsigned int) const = 0; virtual bool IsEmpty () const = 0; virtual bool IsLeaf () const = 0; virtual unsigned int Degree () const = 0; virtual int Height () const; virtual void DepthFirstTraversal (PrePostVisitor&) const; virtual void BreadthFirstTraversal (Visitor&) const; void Accept (Visitor&) const;};

Page 67: Árvores B Implementação pelos FrameWork Bruno Preiss

67

Declaraçã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 68: Árvores B Implementação pelos FrameWork Bruno Preiss

68

Classe MwayTree: Definição// 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; Object& Find (Object const& ) const;

int GetCount() { return numberOfKeys; }};

Page 69: Árvores B Implementação pelos FrameWork Bruno Preiss

69

Funções Membro Construtor e Destrutor da Classe MWayTree

MWayTree::MWayTree (unsigned int n) : m(n)

{

key.SetLength(m);

subtree.SetLength(m);

}

MWayTree::~MWayTree ()

{

}

Page 70: Árvores B Implementação pelos FrameWork Bruno Preiss

70

Funções Membro Subtree e Key da Classe MWayTree

MWayTree& MWayTree::Subtree (unsigned int i) const

{return *subtree[m];

}

Object& MWayTree::Key(unsigned int i) const{return *key[m];

}

Page 71: Árvores B Implementação pelos FrameWork Bruno Preiss

71

Método Find

Recebe uma referencia a um objeto e localiza o item na árvore de busca que coincide com o objeto buscado

Caso o objeto buscado não exista retorna uma instancia de NullObject

Page 72: Árvores B Implementação pelos FrameWork Bruno Preiss

72

Método Find da Classe MWayTreesem uso de função FindIndex // 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 73: Árvores B Implementação pelos FrameWork Bruno Preiss

73

Método FindIndex

Recebe uma referencia a um objeto x e retorna i que é o maior valor tal que x ≥ ki, sendo ki a chave de ordem i no nó

Page 74: Árvores B Implementação pelos FrameWork Bruno Preiss

74

Método FindIndex da Classe MWayTree// pgm10_16.cppunsigned int MWayTree::FindIndex (Object const& object) const{ if (IsEmpty ())

throw std::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 75: Árvores B Implementação pelos FrameWork Bruno Preiss

75

Método Find da Classe MWayTreecom uso de função FindIndex

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 76: Árvores B Implementação pelos FrameWork Bruno Preiss

76

Classe Btree (1)// pgm10_19.cppclass BTree : public MWayTree{ BTree* parent; void InsertPair (Object&, BTree&); void RemovePair(unsigned int index); 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&); bool IsFull();

unsigned int GetMin (); void Balance (); void PrintTree (Visitor& visitor, int spaces); unsigned int GetCountRightSister (unsigned int index);

unsigned int GetCountLeftSister (unsigned int index); void RRRotation (unsigned int index); void LLRotation (unsigned int index); void TrimmRoot (); virtual MWayTree& Subtree (unsigned int) const ;

virtual bool IsEmpty () const ; virtual bool IsLeaf () const ; virtual unsigned int Degree () const ;

Page 77: Árvores B Implementação pelos FrameWork Bruno Preiss

77

Classe Btree (2) Object& FindMin () const;

Object& FindMax () const;Object& Key(unsigned int );

bool IsMember (Object const& obj) const { return ( Find(obj) != NullObject::Instance() ); };

int CompareTo (Object const&) const { return 0; }; HashValue Hash () const { return 0; }; void Put (std::ostream&) const {};

protected:void Concatenation (int index);

public: BTree (unsigned int); BTree (unsigned int, BTree&);

void Insert (Object&); void Withdraw (Object&);};

Page 78: Árvores B Implementação pelos FrameWork Bruno Preiss

78

Função Membro Construtor da Classe BTree

BTree::BTree (unsigned int m,

BTree& ancestral) : MWayTree(m)

{

this->parent = &ancestral;

}

Page 79: Árvores B Implementação pelos FrameWork Bruno Preiss

79

Método Insert da Classe Btree (1)

// pgm10_20.cppvoid BTree::Insert (Object& object){ if (IsEmpty ()) // ponteiro aterrado (folha) {

if (parent == 0) // nó sem pai (raiz){ AttachSubtree (0, *new BTree (m, *this));

// nova árvore é o filho 0 AttachKey (1, object);

// objeto a inserir é a chave 1 AttachSubtree (1, *new BTree (m, *this));

// nova árvore é o filho 1 numberOfKeys = 1;}

Page 80: Árvores B Implementação pelos FrameWork Bruno Preiss

80

Método Insert da Classe Btree (2)

else // folha com pai // inserir no ancestral o objeto e árvore filho m

parent->InsertPair (object, *new BTree (m, *parent)); } else // não estamos em folha {

unsigned int const index = FindIndex (object); // index é, no nó,a posição “abaixo” de object

if (index != 0 && object == *key [index]) throw std::domain_error (“chave duplicada"); subtree [index]->Insert (object);

// inserir o objeto na sub árvore adequada }}

Page 81: Árvores B Implementação pelos FrameWork Bruno Preiss

81

Método InsertPair da Clase Btree (1)

// pgm10_21.cpp

void BTree::InsertPair (Object& object, BTree& child)

{

unsigned int const index = FindIndex (object);

// posição da inserção

BTree& extraTree = InsertSubtree (index + 1, child);

// insere sub árvore à direita de index

Object& extraKey = InsertKey (index + 1, object);

// insere objeto à direita de index

Page 82: Árvores B Implementação pelos FrameWork Bruno Preiss

82

Método InsertPair da Clase Btree (2)

if (++numberOfKeys == m) // nó transborda {

if (parent == 0) // era a raiz{ BTree& left = *new BTree (m, *this);

// left é nó de ordem m filho do corrente BTree& right = *new BTree (m, *this);

// right é nó de ordem m filho do corrente 

left.AttachLeftHalfOf (*this); // adicionar a left a metade esquerda do nó corrente

right.AttachRightHalfOf (*this, extraKey, extraTree); // adicionar a right o par inserido e a metade direita // do nó corrente

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

Page 83: Árvores B Implementação pelos FrameWork Bruno Preiss

83

Método InsertPair da Clase Btree (3)

else // nó transborda mas tem ancestral{ numberOfKeys = (m + 1)/2 - 1;

// nova população da página corrente BTree& right = *new BTree (m, *parent);

// right nova página irmã direita right.AttachRightHalfOf (*this, extraKey, extraTree);

// adicionar a right o par a inserir e a metade direita // do nó corrente

parent->InsertPair (*key [(m + 1)/2], right); // inserir no ancestral o par objeto do meio e // a página right

} }}

Page 84: Árvores B Implementação pelos FrameWork Bruno Preiss

84

Função Membro AttachSubtree

void BTree::AttachSubtree (unsigned

int i, MWayTree& child)

{

subtree [i] = &child;

((BTree&) child).parent == this;

}

Page 85: Árvores B Implementação pelos FrameWork Bruno Preiss

85

Função Membro InsertSubtree (1)BTree& BTree::InsertSubtree (unsigned int index, BTree& child) { //Esta função vai retornar null quando o nó não estiver cheio // quando o nó estiver cheio retorna a sub árvore que transbordou if (IsFull ()) { if (index == m) // a sub árvore a inserir era maior do que as demais e vai sobrar return child; else { // vai sobrar a sub árvore que era a maior de todas BTree& extraTree = (BTree&) *subtree [numberOfKeys]; for (int i = numberOfKeys - 1; i >= index; --i) { subtree[i + 1] = subtree[i]; }

AttachSubtree(index, child);

return extraTree; } }

Page 86: Árvores B Implementação pelos FrameWork Bruno Preiss

86

Função Membro InsertSubtree (2)

else // nó com espaço { child.parent = this; for (int i = numberOfKeys; i >= index; --i)

{ subtree [i + 1] = subtree [i]; } subtree [index] = &child; }

return (BTree&) NullObject::Instance(); }

Page 87: Árvores B Implementação pelos FrameWork Bruno Preiss

87

Função Membro InsertKey (1)Object& BTree::InsertKey (unsigned int index, Object& object) { //Esta função vai retornar null quando o nó não estiver cheio // quando o nó estiver cheio retorna a chave que transbordou if (IsFull ()) { if (index == m) // a chave a inserir era maior do que as demais e vai sobrar return object; else { // vai sobrar a chave que era a maior de todas Object& extraKey = *key [numberOfKeys]; for (int i = numberOfKeys - 1; i >= index; --i) { key [i + 1] = key [i]; } key [index] = &object;

return extraKey; } }

Page 88: Árvores B Implementação pelos FrameWork Bruno Preiss

88

Função Membro InsertKey (2)

else // nó com espaço { for (int i = numberOfKeys; i >= index; --i) { key [i + 1] = key [i]; } key [index] = &object; } return NullObject::Instance (); }

Page 89: Árvores B Implementação pelos FrameWork Bruno Preiss

89

Função Membro Withdraw (1)// pgm10_18.cppvoid MWayTree::Withdraw (Object& object){ if (IsEmpty ())

throw InvalidOperationException("objeto nao 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);}else if (!subtree [index]->IsEmpty ()){ Object& min = subtree [index]->FindMin (); key [index] = &min; subtree [index]->Withdraw (min);}

Page 90: Árvores B Implementação pelos FrameWork Bruno Preiss

90

Função Membro Withdraw (2)else

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

} else

subtree [index]->Withdraw (object); if (numberOfKeys < GetMin()) if (parent != 0)Balance(); else if (numberOfKeys == 0) RootTrim();

}

Page 91: Árvores B Implementação pelos FrameWork Bruno Preiss

91

Função Membro FindMin

Object& BTree::FindMin () const{ if (IsEmpty ())return NullObject::Instance ();

else if (subtree[0]->IsEmpty ()) return *key[1];

else return subtree[0]->FindMin();

}

Page 92: Árvores B Implementação pelos FrameWork Bruno Preiss

92

Função Membro FindMax

Object& BTree::FindMax () const

{

if (IsEmpty ())

return NullObject::Instance ();

else if (subtree[numberOfKeys]->IsEmpty ())

return *key[numberOfKeys];

else

return subtree[numberOfKeys]->FindMax();

}

Page 93: Árvores B Implementação pelos FrameWork Bruno Preiss

93

Função Membro GetMin e IsFull

unsigned int BTree::GetMin ()

{

return ((m + 1) / 2) - 1;

}

bool BTree::IsFull ()

{

return (m - 1) == numberOfKeys;

}

Page 94: Árvores B Implementação pelos FrameWork Bruno Preiss

94

Função Membro Balance (1)void BTree::Balance () { int parentIndex = parent->FindIndex (this-

>key [1]);

int leftSister = GetCountLeftSister (parentIndex); int rightSister = GetCountRightSister (parentIndex);

if (leftSister > GetMin ()) { parent->LLRotation (parentIndex); }

Page 95: Árvores B Implementação pelos FrameWork Bruno Preiss

95

Função Membro Balance (2)

else if (rightSister > GetMin ()) { parent->RRRotation (parentIndex); } // else if (parentIndex + 2 != 0 && ...

else if (leftSister >= rightSister) { parent->Concatenation (parentIndex); } else { parent->Concatenation (parentIndex + 1); } }

Page 96: Árvores B Implementação pelos FrameWork Bruno Preiss

96

Função Membro PrintTree (1)

void BTree::PrintTree (Visitor visitor, int spaces) { if (!IsEmpty ()) { for (int i = numberOfKeys + 1; i >= 0; --i) { if (i <= numberOfKeys) { ((BTree*) subtree [i])->printTree (visitor, spaces + 3); }

Page 97: Árvores B Implementação pelos FrameWork Bruno Preiss

97

Função Membro printTree (2)

if (i >= 1 && i <= numberOfKeys) { for (int o = spaces; o > 0; --o) printf (" "); visitor.Visit (*key [i]); } } } else if (parent == 0) throw new ContainerEmptyException ("Arvore vazia!"); }

Page 98: Árvores B Implementação pelos FrameWork Bruno Preiss

98

Função Membro GetCountLeftSister

unsigned int BTree::GetCountLeftSister (unsigned int index)

{ if (index == 0) return GetMin () - 1; else return parent->subtree [index - 1]-> GetCount(); }

Page 99: Árvores B Implementação pelos FrameWork Bruno Preiss

99

Função Membro GetCountRightSister

unsigned int BTree::GetCountRightSister (unsigned int index)

{ if (index == this->parent->numberOfKeys) return GetMin () - 1; else return parent->subtree [index + 1]-> GetCount(); }

Page 100: Árvores B Implementação pelos FrameWork Bruno Preiss

100

Função Membro LLRotationvoid BTree::LLRotation (unsigned int index){ if (isEmpty ()) throw new InvalidOperationException ("Operação inválida!"); int lastPosition; lastPosition = subtree [index - 1]->GetCount (); Object & tempKey = subtree[index - 1]->Key(lastPosition); BTree & tempSubtree = (BTree&) subtree[index - 1]-

>Subtree(lastPosition);

((BTree*)subtree [index])->InsertPair(*key [index], tempSubtree);

key [index] = &tempKey; ((BTree*) subtree [index - 1])->RemovePair (lastPosition);}

Page 101: Árvores B Implementação pelos FrameWork Bruno Preiss

101

Função Membro RRRotationvoid BTree::RRRotation (unsigned int index){ if (IsEmpty ()) throw new InvalidOperationException ("Operação inválida!");

BTree & tempSubtree = (BTree &) subtree [index + 1]->Subtree(0); ((BTree*) subtree [index])->InsertPair (*key [index + 1], tempSubtree); key[index + 1] = &subtree[index + 1]->Key(1); ((Tree&)subtree [index + 1]->Subtree(0)) = ((Tree&)subtree [index + 1]->Subtree(1)); ((BTree*) subtree [index + 1])->RemovePair (1);}

Page 102: Árvores B Implementação pelos FrameWork Bruno Preiss

102

Função Membro Concatenation

void BTree::Concatenation (int index){ ((BTree*) subtree [index - 1])->InsertPair (*key [index], (BTree&) subtree [index]->Subtree(0)); for (int i = 1; i <= subtree [index]->GetCount (); ++i) { ((BTree*) subtree [index - 1])->InsertPair (subtree

[index]->Key(i), (BTree&) subtree [index]->Subtree(i)); } --numberOfKeys; for (i = index; i <= numberOfKeys; ++i) { key [i] = key [i + 1]; subtree [i] = subtree [i + 1]; } key [i] = 0; subtree [i] = 0;}

Page 103: Árvores B Implementação pelos FrameWork Bruno Preiss

103

Função Membro TrimmRootvoid BTree::TrimmRoot () { { numberOfKeys = subtree [0]->GetCount ();

int i; for (i = numberOfKeys; i > 0; --i) { key [i] = &subtree [0]->Key(i); subtree [i] = &subtree [0]->Subtree(i); ((BTree*) subtree [i])->parent = this; }

subtree [i] = &subtree [0]->Subtree(i); ((BTree*) subtree [i])->parent = this; } }

Page 104: Árvores B Implementação pelos FrameWork Bruno Preiss

104

Função Membro RemovePair

void BTree::RemovePair (unsigned int index)

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

key [i] = 0; subtree [i] = 0; }

Page 105: Árvores B Implementação pelos FrameWork Bruno Preiss

105

Função Membro AttachLeftHalfOf

void BTree::AttachLeftHalfOf (BTree const& tree){

AttachSubtree (0, *tree.subtree [0]);

numberOfKeys = 0; for (int ind = 1; ind < tree.m / 2; ++ind) { InsertPair (*tree.key [ind], (BTree&)(*tree.subtree [ind]));

} }

Page 106: Árvores B Implementação pelos FrameWork Bruno Preiss

106

Função Membro AttachRightHalfOf

void BTree::AttachRightHalfOf (BTree const&, Object& extraKey, BTree& tree){ AttachSubtree (0, *tree.subtree [(m + 1) / 2]);

numberOfKeys = 0; for (int ind = tree.m - 1; ind > tree.m + 1) / 2; --ind) { InsertPair (*tree.key[ind], (BTree&) *tree.subtree[ind]);

} }

Page 107: Árvores B Implementação pelos FrameWork Bruno Preiss

107

class 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&);

bool IsFull();public: BTree (unsigned int); BTree (unsigned int, BTree&);

void Insert (Object&); void Withdraw (Object&);};