Advertisement
dcndrd

BinaryTree

Nov 14th, 2014
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.49 KB | None | 0 0
  1. package br.uefs.ecomp.treeStock.util;
  2.  
  3. import java.util.Iterator;
  4.  
  5. /**
  6.  * Classe que implementa uma Árvore AVL.
  7.  *
  8.  * @author Daniel Coelho de Andrade
  9.  */
  10. public class BinaryTree implements IBinaryTree {
  11.  
  12.     private Node root;
  13.  
  14.     /**
  15.      * Adiciona um item na árvore chamando o método recursivo.
  16.      *
  17.      * @param item Item a ser adicionado.
  18.      * @throws br.uefs.ecomp.treeStock.util.DadoDuplicadoException
  19.      */
  20.     @Override
  21.     public void inserir(Comparable item) throws DadoDuplicadoException{
  22.         this.root = this.insert(item, root);
  23.     }
  24.  
  25.     /**
  26.      * Insere um item na ávore.
  27.      *
  28.      * @param item Item a ser removido.
  29.      * @param lRoot Raiz local.
  30.      * @return A raiz da nova árvore.
  31.      */
  32.     private Node insert(Comparable item, Node lRoot) throws DadoDuplicadoException {
  33.         if (lRoot == null) {
  34.             lRoot = new Node(item);
  35.         } else if(item.compareTo(lRoot.getData()) == 0 ){
  36.             throw new DadoDuplicadoException("Dado duplicado");
  37.         }
  38.         else if (item.compareTo(lRoot.getData()) < 0) {
  39.             lRoot.setLeftChild(this.insert(item, lRoot.getLeftChild()));
  40.  
  41.             int l = this.heigth(lRoot.getLeftChild());
  42.             int r = this.heigth(lRoot.getRightChild());
  43.  
  44.             if (r - l == -2) {
  45.                 if (item.compareTo(lRoot.getData()) < 0) {
  46.                     lRoot = this.rotateLeft(lRoot);
  47.                 } else {
  48.                     lRoot = this.doubleRotateLeft(lRoot);
  49.                 }
  50.             }
  51.         } else if (item.compareTo(lRoot.getData()) > 0) {
  52.             lRoot.setRightChild(this.insert(item, lRoot.getRightChild()));
  53.  
  54.             int r = this.heigth(lRoot.getRightChild());
  55.             int l = this.heigth(lRoot.getLeftChild());
  56.  
  57.             if (r - l == 2) {
  58.                 if (item.compareTo(lRoot.getData()) > 0) {
  59.                     lRoot = this.rotateRight(lRoot);
  60.                 } else {
  61.                     lRoot = this.doubleRotateRight(lRoot);
  62.                 }
  63.             }
  64.         }
  65.         //else ;
  66.  
  67.         //lRoot.setHeight(max(this.heigth(lRoot.getLeftChild()), this.heigth(lRoot.getRightChild())) + 1);
  68.         return lRoot;
  69.     }
  70.  
  71.     /**
  72.      * Rotação à esquerda.
  73.      */
  74.     private Node rotateLeft(Node lRoot) {
  75.         Node newRoot = lRoot.getLeftChild();
  76.         lRoot.setLeftChild(newRoot.getRightChild());
  77.         newRoot.setRightChild(lRoot);
  78.  
  79.         //lRoot.setHeight(this.max(this.heigth(lRoot.getLeftChild()), this.heigth(lRoot.getRightChild())) + 1);
  80.         //newRoot.setHeight(this.max(this.heigth(newRoot.getLeftChild()), this.heigth(newRoot.getRightChild())) + 1);
  81.         return newRoot;
  82.     }
  83.  
  84.     /**
  85.      * Rotação à direita.
  86.      */
  87.     private Node rotateRight(Node lRoot) {
  88.         Node newRoot = lRoot.getRightChild();
  89.         lRoot.setRightChild(newRoot.getLeftChild());
  90.         newRoot.setLeftChild(lRoot);
  91.  
  92.         //lRoot.setHeight(this.max(this.heigth(lRoot.getLeftChild()), this.heigth(lRoot.getRightChild())) + 1);
  93.         // newRoot.setHeight(this.max(this.heigth(newRoot.getLeftChild()), this.heigth(newRoot.getRightChild())));
  94.         return newRoot;
  95.     }
  96.  
  97.     /**
  98.      * Rotação dupla à esquerda. Primeiro rotaciona o filho esquerdo com filho
  99.      * direito, depois o nó lRoot com seu filho esquerdo
  100.      */
  101.     private Node doubleRotateLeft(Node lRoot) {
  102.         lRoot.setLeftChild(this.rotateRight(lRoot.getLeftChild()));
  103.  
  104.         return this.rotateLeft(lRoot);
  105.     }
  106.  
  107.     /**
  108.      * Rotação dupla à direita. Primeiro rotaciona o filho direito com filho
  109.      * esquerdo, depois o nó lRoot com seu filho direito
  110.      */
  111.     private Node doubleRotateRight(Node lRoot) {
  112.         lRoot.setRightChild(this.rotateLeft(lRoot.getRightChild()));
  113.  
  114.         return this.rotateRight(lRoot);
  115.     }
  116.  
  117.     /**
  118.      * Procura um item na ávore.
  119.      *
  120.      * @param item Item a ser procurado.
  121.      * @return O item procurado.
  122.      * @throws br.uefs.ecomp.treeStock.util.DadoNaoEncontradoException
  123.      */
  124.     @Override
  125.     public Object buscar(Comparable item) throws DadoNaoEncontradoException {
  126.         Node current = root;
  127.  
  128.         while (current != null) {
  129.  
  130.             if (current.getData().compareTo(item) == 0) {
  131.                 //return current.getData();
  132.                 return current.getData();
  133.             }
  134.             if (current.getData().compareTo(item) < 0) {
  135.                 current = current.getRightChild();
  136.             } else {
  137.                 current = current.getLeftChild();
  138.             }
  139.         }
  140.  
  141.        
  142.             throw new DadoNaoEncontradoException("Elemento não existente");
  143.        
  144.     }
  145.  
  146.     /**
  147.      * Procura e remove um elemento da árvore.
  148.      *
  149.      * @param item Item a ser removido.
  150.      * @throws br.uefs.ecomp.treeStock.util.DadoNaoEncontradoException
  151.      */
  152.     @Override
  153.     public void remover(Comparable item) throws DadoNaoEncontradoException {
  154.         Node current = root;
  155.         Node parent = current;
  156.        
  157.         if (root == null) {
  158.             throw new DadoNaoEncontradoException();
  159.         }
  160.        
  161.         //Procura o elemento a ser removido
  162.         while (current.getData().compareTo(item) != 0) {
  163.             if (current.getData().compareTo(item) < 0) {
  164.                 parent = current;
  165.                 current = current.getRightChild();
  166.                 //isLeftChild = false;
  167.             } else {
  168.                 parent = current;
  169.                 current = current.getLeftChild();
  170.                 //isLeftChild = true;
  171.             }
  172.  
  173.             if (current == null) {
  174.                 throw new DadoNaoEncontradoException("Elemento inexistente");
  175.             }
  176.         }
  177.  
  178.         //Nó a ser removido é uma folha.
  179.         if (!current.hasLeftChild() && !current.hasRigthChild()) {
  180.             if (current == root) {
  181.                 root = null;
  182.             } else if (parent.getLeftChild() == current) {
  183.                 parent.setLeftChild(null);
  184.             } else {
  185.                 parent.setRightChild(null);
  186.             }
  187.         } //Nó a ser removido só tem filho esquerdo
  188.         else if (current.hasLeftChild() && !current.hasRigthChild()) {
  189.             if (current == root) {
  190.                 root = current.getLeftChild();
  191.             } else if (parent.getLeftChild() == current) {
  192.                 parent.setLeftChild(current.getLeftChild());
  193.             } else {
  194.                 parent.setRightChild(current.getLeftChild());
  195.             }
  196.         } //Nó a ser removido só tem filho direito
  197.         else if (!current.hasLeftChild() && current.hasRigthChild()) {
  198.             if (current == root) {
  199.                 root = current.getRightChild();
  200.             } else if (parent.getLeftChild() == current) {
  201.                 parent.setLeftChild(current.getRightChild());
  202.             } else {
  203.                 parent.setRightChild(current.getRightChild());
  204.             }
  205.         } //Nó a ser removido tem filho direito e filho esquerdo
  206.         else {
  207.             Node sucessor = this.getSucessor(current);
  208.  
  209.             if (current == root) {
  210.                 root = sucessor;
  211.             } else if (parent.getLeftChild() == current) {
  212.                 parent.setLeftChild(sucessor);
  213.             } else {
  214.                 parent.setRightChild(sucessor);
  215.             }
  216.  
  217.             sucessor.setLeftChild(current.getLeftChild());
  218.         }
  219.         this.searchAndBalanceInRoute(parent);
  220.     }
  221.  
  222.     /**
  223.      * Verifica o balanceamento dos ancestrais de um nó excluído. Se algum nó
  224.      * estiver desbalaceado, o balanceia.
  225.      *
  226.      * @param lRoot Raiz local
  227.      */
  228.     private void searchAndBalanceInRoute(Node lRoot) {
  229.         Node current = this.root;
  230.         if (lRoot == null || current == null) {
  231.             return;
  232.         }
  233.  
  234.         current = this.getParent(lRoot);
  235.         while (current != null) {
  236.  
  237.             int l = this.heigth(current.getLeftChild());
  238.             int r = this.heigth(current.getRightChild());
  239.             if (r - l == -2) {
  240.                 if (lRoot.getData().compareTo(current.getData()) < 0) {
  241.                     current = this.rotateLeft(current);
  242.                 } else {
  243.                     current = this.doubleRotateLeft(current);
  244.                 }
  245.             } else if (r - l == 2) {
  246.                 if (lRoot.getData().compareTo(current.getData()) > 0) {
  247.                     current = this.rotateRight(current);
  248.                 } else {
  249.                     current = this.doubleRotateRight(current);
  250.                 }
  251.             }
  252.             current = this.getParent(current);
  253.         }
  254.     }
  255.  
  256.     /**
  257.      * Procura o pai de um nó.
  258.      *
  259.      * @param child Nó que o pai deve ser buscado.
  260.      * @return O pai do nó.
  261.      */
  262.     private Node getParent(Node child) {
  263.         Node current = root;
  264.  
  265.         while (current != null) {
  266.  
  267.             if (current.getLeftChild() == child) {
  268.                 return current;
  269.             } else if (current.getRightChild() == child) {
  270.                 return current;
  271.             }
  272.  
  273.             if (current.getData().compareTo(child.getData()) < 0) {
  274.                 current = current.getRightChild();
  275.             } else {
  276.                 current = current.getLeftChild();
  277.             }
  278.         }
  279.  
  280.         return null;
  281.     }
  282.  
  283.     /**
  284.      * Procura o sucessor de um nó que será excluido e rearranja os filhos do
  285.      * sucessor e do nó que será excluído.
  286.      *
  287.      * @param delete Nó que será deletado.
  288.      * @return O sucessor do nó que será excluído.
  289.      */
  290.     private Node getSucessor(Node delete) {
  291.         Node sucessor = delete;
  292.         Node sucessorParent = sucessor;
  293.         Node current;
  294.  
  295.         if (sucessor == null) {
  296.             return null;
  297.         } else {
  298.             current = sucessor.getRightChild();
  299.         }
  300.  
  301.         while (current != null) {
  302.             sucessorParent = sucessor;
  303.             sucessor = current;
  304.             current = current.getLeftChild();
  305.         }
  306.  
  307.         if (sucessor != delete.getRightChild()) {
  308.             sucessorParent.setLeftChild(sucessor.getRightChild());
  309.             sucessor.setRightChild(delete.getRightChild());
  310.         }
  311.  
  312.         return sucessor;
  313.     }
  314.  
  315.     /**
  316.      * Calcula a altura de um nó
  317.      *
  318.      * @param current Nó que a altura deve ser calculada.
  319.      * @return A altura do nó.
  320.      */
  321.     private int heigth(Node current) {
  322.         if (current == null) {
  323.             return -1;
  324.         }
  325.         if (!current.hasLeftChild() && !current.hasRigthChild()) {
  326.             return 0;
  327.         } else if (current.hasRigthChild()) {
  328.             return 1 + heigth(current.getRightChild());
  329.         } else if (current.hasLeftChild()) {
  330.             return 1 + heigth(current.getLeftChild());
  331.         } else {
  332.             return 1 + this.max(heigth(current.getLeftChild()), heigth(current.getRightChild()));
  333.         }
  334.     }
  335.  
  336.     /**
  337.      * Calcula o maior número entre dois números.
  338.      *
  339.      * @param a Primeiro número.
  340.      * @param b Segundo número.
  341.      * @return O maior número
  342.      */
  343.     private int max(int a, int b) {
  344.         return a > b ? a : b;
  345.     }
  346.  
  347.     /**
  348.      * Chama a função recursiva para a contagem dos nós.
  349.      *
  350.      * @return O número de nós da árvore.
  351.      */
  352.     public int countNodes() {
  353.         return this.countNodes(root);
  354.     }
  355.  
  356.     private int countNodes(Node localRoot) {
  357.         int tam = 0;
  358.         if (localRoot != null) {
  359.             tam = 1 + this.countNodes(localRoot.getLeftChild()) + countNodes(localRoot.getRightChild());
  360.         }
  361.         return tam;
  362.     }
  363.    
  364.     /**
  365.      *
  366.      * @return Um iterador.
  367.      */
  368.     @Override
  369.     public Iterator iterator() {
  370.         return new inOrderIterator(root);
  371.     }
  372.    
  373.     public void debug() {
  374.         this.debug(root);
  375.     }
  376.  
  377.     private void debug(Node lRoot) {
  378.         if (lRoot != null) {
  379.             this.debug(lRoot.getLeftChild());
  380.             System.out.println(this.heigth(lRoot.getRightChild()) - this.heigth(lRoot.getLeftChild()));
  381.             this.debug(lRoot.getRightChild());
  382.         }
  383.     }
  384.  
  385.     @Override
  386.     public boolean contains(Comparable o) {
  387.         Node current = root;
  388.         while (current != null) {
  389.  
  390.             if (current.getData().compareTo(o) == 0) {
  391.                 return true;
  392.             }
  393.             if (current.getData().compareTo(o) < 0) {
  394.                 current = current.getRightChild();
  395.             } else {
  396.                 current = current.getLeftChild();
  397.             }
  398.         }
  399.         return false;
  400.     }
  401.    
  402. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement