A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

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

Apresentações semelhantes


Apresentação em tema: "Árvores B Implementação pelos FrameWork Bruno Preiss."— Transcrição da apresentação:

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

2 Árvores B FrameWork Java de Bruno Preiss

3 3 Framework de Árvores e Busca

4 4 Interface Comparable //pgm05_01.txt public 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); }

5 5 Declaração da classe AbstractObject // pgm05_02.txt public 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; }

6 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 ()); } //... }

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

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

9 9 Interface Tree //pgm09_01.txt public 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); }

10 10 Interface SearchTree //pgm10_01.txt public interface SearchTree extends Tree, SearchableContainer { Comparable findMin (); Comparable findMax (); }

11 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; } //... }

12 12 Classe Abstrata AbstractTree // pgm09_02.txt public 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 ()); } //... }

13 13 Árvores MWay

14 14 Classe MwayTree: Métodos construtor e getM //pgm10_14.txt public 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; } //... }

15 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

16 16 Método find da Classe MWayTree //pgm10_16.txt public 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); }

17 17 Método findIndex Recebe um objeto x e retorna i que é o maior valor tal que x k i, sendo k i a chave de ordem i no nó

18 18 Método findIndex da Classe MWayTree //pgm10_17.txt public 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; }

19 19 Classe BTree // pgm10_20.txt public 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; } //... }

20 20 Método insert da Classe BTree Insere uma chave em uma página de árvore B Se 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 insertPair Se 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)

21 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; } else parent.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); }

22 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

23 23 Método insertPair da Clase BTree (2) A página transbordou e é preciso balancear a árvore Se 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

24 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)

25 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; }

26 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); }

27 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

28 28 Método attachSubtree public void attachSubtree (int i, MWayTree arg) { BTree btree = (BTree) arg; subtree [i] = btree; btree.parent = this; }

29 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]); }

30 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]); }

31 31 Método insertSubtree Recebe um inteiro índice e uma sub árvore e deve inserir na correta posição do array de sub árvores Caso 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

32 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); }

33 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; }

34 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

35 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; }

36 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; }

37 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

38 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

39 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

40 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); }

41 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 (); }

42 42 Métodos getMin e isFull public int getMin () { return ((getM () + 1) / 2) - 1; } public boolean isFull () { return getM () - 1 == count; }

43 43 Método balance Equilibra uma página sub povoada Determina a posição no pai Obtém a população das irmãs esquerda e direita Caso a população da esquerda seja maior do que o mínimo executa uma rotação à esquerda Senão se a população da direita for maior do que o mínimo executa uma rotação à direita Caso 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

44 44 Método balance public 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); }

45 45 Método printTree public 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!"); }

46 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 getCount parent.subtree[index - 1].getCount()

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

48 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 getCount parent.subtree[index + 1].getCount()

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

50 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 anterior key[index] recebe o último objeto da irmã esquerda O último objeto da irmã esquerda e a sub árvore correspondente são removidos pelo método removePair

51 51 Método doLLRotation protected 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); }

52 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 anterior key[index + 1] recebe o primeiro objeto da irmã direita O primeiro objeto da irmã direita e a sub árvore correspondente são removidos pelo método removePair

53 53 Método doRRRotation protected 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); }

54 54 Método concatenation Concatena a página filha corrente (que será desalocada) com sua irmã esquerda A 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 insertPair Todas as chaves e sub árvores correspondentes da página filha corrente são copiados para a irmã esquerda pelo método insertPair Todas 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 esquerda A última chave e a última sub árvore da página corrente são anuladas

55 55 Método concatenation protected 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; }

56 56 Método rootTrim protected 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; }

57 57 Método removePair Remove de uma página a chave key [index] e a sub árvore correspondente O contador de objetos é decrementado Todas 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 esquerda A última chave e a última sub árvore da página corrente são anuladas

58 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; }

59 Árvores B FrameWork C++ de Bruno Preiss

60 60 Framework de Árvores e Busca

61 61 Árvores MWay

62 62 Declaração da Classe Object // pgm05_01.cpp class 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; };

63 63 Declaração da Classe Container // pgm05_09.cpp class 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; };

64 64 Declaração da Classe Ownership // pgm05_17.cpp class 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; } };

65 65 Declaração da Classe SearchableContainer // pgm05_21.cpp class 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; };

66 66 Declaração da Classe Tree // pgm09_01.cpp class 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; };

67 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; };

68 68 Classe MwayTree: Definição // pgm10_13.cpp class MWayTree : public SearchTree { protected: unsigned int const m; unsigned int numberOfKeys; Array key; Array 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; } };

69 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 () { }

70 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]; }

71 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

72 72 Método Find da Classe MWayTree sem uso de função FindIndex // pgm10_15.cpp Object& 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); }

73 73 Método FindIndex Recebe uma referencia a um objeto x e retorna i que é o maior valor tal que x k i, sendo k i a chave de ordem i no nó

74 74 Método FindIndex da Classe MWayTree // pgm10_16.cpp unsigned 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; }

75 75 Método Find da Classe MWayTree com 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); }

76 76 Classe Btree (1) // pgm10_19.cpp class 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 ;

77 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&); };

78 78 Função Membro Construtor da Classe BTree BTree::BTree (unsigned int m, BTree& ancestral) : MWayTree(m) { this->parent = &ancestral; }

79 79 Método Insert da Classe Btree (1) // pgm10_20.cpp void 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; }

80 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 }

81 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

82 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; }

83 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 }

84 84 Função Membro AttachSubtree void BTree::AttachSubtree (unsigned int i, MWayTree& child) { subtree [i] = &child; ((BTree&) child).parent == this; }

85 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; }

86 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(); }

87 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; }

88 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 (); }

89 89 Função Membro Withdraw (1) // pgm10_18.cpp void 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); }

90 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(); }

91 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(); }

92 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(); }

93 93 Função Membro GetMin e IsFull unsigned int BTree::GetMin () { return ((m + 1) / 2) - 1; } bool BTree::IsFull () { return (m - 1) == numberOfKeys; }

94 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); }

95 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); }

96 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); }

97 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!"); }

98 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(); }

99 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(); }

100 100 Função Membro LLRotation void 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); }

101 101 Função Membro RRRotation void 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); }

102 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 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; }

103 103 Função Membro TrimmRoot void 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; } }

104 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; }

105 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])); } }

106 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]); }

107 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&); };


Carregar ppt "Árvores B Implementação pelos FrameWork Bruno Preiss."

Apresentações semelhantes


Anúncios Google