1 / 107

Árvores B

Árvores B. Implementação pelos FrameWork Bruno Preiss. Árvores B. FrameWork Java de Bruno Preiss. Framework de Árvores e Busca. Interface Comparable. //pgm05_01.txt public interface Comparable { boolean isLT (Comparable object); boolean isLE (Comparable object);

cyrah
Download Presentation

Árvores B

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Árvores B FrameWork Java de Bruno Preiss

  3. Framework de Árvores e Busca

  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. 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. 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. Interface Container public interface Container extends Comparable { int getCount (); boolean isEmpty (); boolean isFull (); void purge (); void accept (Visitor visitor); Enumeration getEnumeration (); }

  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. 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. Interface SearchTree //pgm10_01.txt public interface SearchTree extends Tree, SearchableContainer { Comparable findMin (); Comparable findMax (); }

  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. 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. Árvores MWay

  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. 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. 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. 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ó

  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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Método attachSubtree public void attachSubtree (int i, MWayTree arg) { BTree btree = (BTree) arg; subtree [i] = btree; btree.parent = this; }

  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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Métodos getMin e isFull public int getMin () { return ((getM () + 1) / 2) - 1; } public boolean isFull () { return getM () - 1 == count; }

  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. 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. 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. 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. Método getCountLeftSister public int getCountLeftSister (int index) { if (index == 0) return getMin () - 1; else return parent.subtree [index - 1].getCount (); }

  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. Método getCountRightSister public int getCountRightSister (int index) { if (index == this.parent.count) return getMin () - 1; else return parent.subtree [index + 1].getCount (); }

  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

More Related