/** * @param root: The element for which to find a successor AVLNode * @return AVLNode<E>: The successor Node * */ private AVLNode<E> findSuccessor(AVLNode<E> root) { AVLNode<E> temp = root; AVLNode<E> parent = null; // if the balance favors the right, traverse right // otherwise, traverse left boolean direction = (temp.getBalance() > 0); parent = temp; temp = (direction) ? temp.getRight() : temp.getLeft(); if (temp == null) return temp; // and find the farthest left-Node on the right side, // or the farthest right-Node on the left side while ((temp.getRight() != null && !direction) || (temp.getLeft() != null && direction)) { parent = temp; temp = (direction) ? temp.getLeft() : temp.getRight(); } // finally, update the successor's parent's references // to adjust for a left child on the right node, or a right // child on the left-node if (temp == parent.getLeft()) { parent.setLeftNode(temp.getRight()); temp.setRightNode(null); } else { parent.setRightNode(temp.getLeft()); temp.setLeftNode(null); } return temp; }
/** * @param element: The element to remove from the AVLTree * @param temp: The root node of the subtree * <p>This method recursively traverses the AVLTree based on the ordering of the element with * respect to the Tree's elements. If the element is not found, then nothing happens. * Otherwise, the element is removed, and either the far-right element on its left child or * the far left element on its right child replaces it. * */ private void remove(E element, AVLNode<E> temp) { if (temp == null) return; int compare = 0; if (temp != rootAbove) compare = element.compareTo(temp.getElement()); boolean direction = (compare > 0 && temp != rootAbove); AVLNode<E> child = direction ? temp.getRight() : temp.getLeft(); if (child == null) return; // if the root is perfectly balanced, slide the left Node up // and reinsert the left.right element if necessary if (temp == rootAbove && child.getBalance() == 0 && child.getElement().equals(element)) { AVLNode<E> newRoot = child.getLeft(); if (newRoot == null) { rootAbove.setLeftNode(null); return; } else { enactRemoval(temp, child, false); return; } } // if the element is found and the root is not // perfectly balanced, remove it using enactRemoval() else if (element.compareTo(child.getElement()) == 0) { enactRemoval(temp, child, direction); } // otherwise, recursively traverse the tree else { remove(element, child); } }
/** * @param rotateBase: The root of the subtree that is being rotated * @param rootAbove: The AVLNode that points to rotateBase * <p>This method rotates the subtree balancing it to within a margin of |1|. */ public void rotate(AVLNode<E> rotateBase, AVLNode<E> rootAbove) { int balance = rotateBase.getBalance(); if (Math.abs(balance) < 2) { // System.out.println("No rotate"); } // gets the child on the side with the greater height AVLNode<E> child = (balance < 0) ? rotateBase.getLeft() : rotateBase.getRight(); if (child == null) return; int childBalance = child.getBalance(); AVLNode<E> grandChild = null; // both the child and grandchild are on the // left side, so rotate the child up to the root position if (balance < -1 && childBalance < 0) { if (rootAbove != this.rootAbove && rootAbove.getRight() == rotateBase) { rootAbove.setRightNode(child); } else { rootAbove.setLeftNode(child); } grandChild = child.getRight(); child.setRightNode(rotateBase); rotateBase.setLeftNode(grandChild); return; } // both the child and the grandchild are on the // right side, so rotate the child up to the root position else if (balance > 1 && childBalance > 0) { if (rootAbove != this.rootAbove && rootAbove.getRight() == rotateBase) { rootAbove.setRightNode(child); } else { rootAbove.setLeftNode(child); } grandChild = child.getLeft(); child.setLeftNode(rotateBase); rotateBase.setRightNode(grandChild); return; } // the child is on the left side, but the grandchild is on the // right side, so rotate the grandchild up to the child position // so the condition of the first if statement is satisfied, // then recurse to have the first if statement evaluated else if (balance < -1 && childBalance > 0) { grandChild = child.getRight(); rotateBase.setLeftNode(grandChild); child.setRightNode(grandChild.getLeft()); grandChild.setLeftNode(child); rotate(rotateBase, rootAbove); return; } // the child is on the right side, but the grandchild is on the // left side, so rotate the grandchild up to the child position // so the condition of the second if statement is satisfied, // then recurse to have the second if statement evaluated else if (balance > 1 && childBalance < 0) { grandChild = child.getLeft(); rotateBase.setRightNode(grandChild); child.setLeftNode(grandChild.getRight()); grandChild.setRightNode(child); rotate(rotateBase, rootAbove); return; } }