AVLTree.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.math3.geometry.partitioning.utilities;

  18. /** This class implements AVL trees.
  19.  *
  20.  * <p>The purpose of this class is to sort elements while allowing
  21.  * duplicate elements (i.e. such that {@code a.equals(b)} is
  22.  * true). The {@code SortedSet} interface does not allow this, so
  23.  * a specific class is needed. Null elements are not allowed.</p>
  24.  *
  25.  * <p>Since the {@code equals} method is not sufficient to
  26.  * differentiate elements, the {@link #delete delete} method is
  27.  * implemented using the equality operator.</p>
  28.  *
  29.  * <p>In order to clearly mark the methods provided here do not have
  30.  * the same semantics as the ones specified in the
  31.  * {@code SortedSet} interface, different names are used
  32.  * ({@code add} has been replaced by {@link #insert insert} and
  33.  * {@code remove} has been replaced by {@link #delete
  34.  * delete}).</p>
  35.  *
  36.  * <p>This class is based on the C implementation Georg Kraml has put
  37.  * in the public domain. Unfortunately, his <a
  38.  * href="www.purists.org/georg/avltree/index.html">page</a> seems not
  39.  * to exist any more.</p>
  40.  *
  41.  * @param <T> the type of the elements
  42.  *
  43.  * @since 3.0
  44.  * @deprecated as of 3.4, this class is not used anymore and considered
  45.  * to be out of scope of Apache Commons Math
  46.  */
  47. @Deprecated
  48. public class AVLTree<T extends Comparable<T>> {

  49.     /** Top level node. */
  50.     private Node top;

  51.     /** Build an empty tree.
  52.      */
  53.     public AVLTree() {
  54.         top = null;
  55.     }

  56.     /** Insert an element in the tree.
  57.      * @param element element to insert (silently ignored if null)
  58.      */
  59.     public void insert(final T element) {
  60.         if (element != null) {
  61.             if (top == null) {
  62.                 top = new Node(element, null);
  63.             } else {
  64.                 top.insert(element);
  65.             }
  66.         }
  67.     }

  68.     /** Delete an element from the tree.
  69.      * <p>The element is deleted only if there is a node {@code n}
  70.      * containing exactly the element instance specified, i.e. for which
  71.      * {@code n.getElement() == element}. This is purposely
  72.      * <em>different</em> from the specification of the
  73.      * {@code java.util.Set} {@code remove} method (in fact,
  74.      * this is the reason why a specific class has been developed).</p>
  75.      * @param element element to delete (silently ignored if null)
  76.      * @return true if the element was deleted from the tree
  77.      */
  78.     public boolean delete(final T element) {
  79.         if (element != null) {
  80.             for (Node node = getNotSmaller(element); node != null; node = node.getNext()) {
  81.                 // loop over all elements neither smaller nor larger
  82.                 // than the specified one
  83.                 if (node.element == element) {
  84.                     node.delete();
  85.                     return true;
  86.                 } else if (node.element.compareTo(element) > 0) {
  87.                     // all the remaining elements are known to be larger,
  88.                     // the element is not in the tree
  89.                     return false;
  90.                 }
  91.             }
  92.         }
  93.         return false;
  94.     }

  95.     /** Check if the tree is empty.
  96.      * @return true if the tree is empty
  97.      */
  98.     public boolean isEmpty() {
  99.         return top == null;
  100.     }


  101.     /** Get the number of elements of the tree.
  102.      * @return number of elements contained in the tree
  103.      */
  104.     public int size() {
  105.         return (top == null) ? 0 : top.size();
  106.     }

  107.     /** Get the node whose element is the smallest one in the tree.
  108.      * @return the tree node containing the smallest element in the tree
  109.      * or null if the tree is empty
  110.      * @see #getLargest
  111.      * @see #getNotSmaller
  112.      * @see #getNotLarger
  113.      * @see Node#getPrevious
  114.      * @see Node#getNext
  115.      */
  116.     public Node getSmallest() {
  117.         return (top == null) ? null : top.getSmallest();
  118.     }

  119.     /** Get the node whose element is the largest one in the tree.
  120.      * @return the tree node containing the largest element in the tree
  121.      * or null if the tree is empty
  122.      * @see #getSmallest
  123.      * @see #getNotSmaller
  124.      * @see #getNotLarger
  125.      * @see Node#getPrevious
  126.      * @see Node#getNext
  127.      */
  128.     public Node getLargest() {
  129.         return (top == null) ? null : top.getLargest();
  130.     }

  131.     /** Get the node whose element is not smaller than the reference object.
  132.      * @param reference reference object (may not be in the tree)
  133.      * @return the tree node containing the smallest element not smaller
  134.      * than the reference object or null if either the tree is empty or
  135.      * all its elements are smaller than the reference object
  136.      * @see #getSmallest
  137.      * @see #getLargest
  138.      * @see #getNotLarger
  139.      * @see Node#getPrevious
  140.      * @see Node#getNext
  141.      */
  142.     public Node getNotSmaller(final T reference) {
  143.         Node candidate = null;
  144.         for (Node node = top; node != null;) {
  145.             if (node.element.compareTo(reference) < 0) {
  146.                 if (node.right == null) {
  147.                     return candidate;
  148.                 }
  149.                 node = node.right;
  150.             } else {
  151.                 candidate = node;
  152.                 if (node.left == null) {
  153.                     return candidate;
  154.                 }
  155.                 node = node.left;
  156.             }
  157.         }
  158.         return null;
  159.     }

  160.     /** Get the node whose element is not larger than the reference object.
  161.      * @param reference reference object (may not be in the tree)
  162.      * @return the tree node containing the largest element not larger
  163.      * than the reference object (in which case the node is guaranteed
  164.      * not to be empty) or null if either the tree is empty or all its
  165.      * elements are larger than the reference object
  166.      * @see #getSmallest
  167.      * @see #getLargest
  168.      * @see #getNotSmaller
  169.      * @see Node#getPrevious
  170.      * @see Node#getNext
  171.      */
  172.     public Node getNotLarger(final T reference) {
  173.         Node candidate = null;
  174.         for (Node node = top; node != null;) {
  175.             if (node.element.compareTo(reference) > 0) {
  176.                 if (node.left == null) {
  177.                     return candidate;
  178.                 }
  179.                 node = node.left;
  180.             } else {
  181.                 candidate = node;
  182.                 if (node.right == null) {
  183.                     return candidate;
  184.                 }
  185.                 node = node.right;
  186.             }
  187.         }
  188.         return null;
  189.     }

  190.     /** Enum for tree skew factor. */
  191.     private static enum Skew {
  192.         /** Code for left high trees. */
  193.         LEFT_HIGH,

  194.         /** Code for right high trees. */
  195.         RIGHT_HIGH,

  196.         /** Code for Skew.BALANCED trees. */
  197.         BALANCED;
  198.     }

  199.     /** This class implements AVL trees nodes.
  200.      * <p>AVL tree nodes implement all the logical structure of the
  201.      * tree. Nodes are created by the {@link AVLTree AVLTree} class.</p>
  202.      * <p>The nodes are not independant from each other but must obey
  203.      * specific balancing constraints and the tree structure is
  204.      * rearranged as elements are inserted or deleted from the tree. The
  205.      * creation, modification and tree-related navigation methods have
  206.      * therefore restricted access. Only the order-related navigation,
  207.      * reading and delete methods are public.</p>
  208.      * @see AVLTree
  209.      */
  210.     public class Node {

  211.         /** Element contained in the current node. */
  212.         private T element;

  213.         /** Left sub-tree. */
  214.         private Node left;

  215.         /** Right sub-tree. */
  216.         private Node right;

  217.         /** Parent tree. */
  218.         private Node parent;

  219.         /** Skew factor. */
  220.         private Skew skew;

  221.         /** Build a node for a specified element.
  222.          * @param element element
  223.          * @param parent parent node
  224.          */
  225.         Node(final T element, final Node parent) {
  226.             this.element = element;
  227.             left         = null;
  228.             right        = null;
  229.             this.parent  = parent;
  230.             skew         = Skew.BALANCED;
  231.         }

  232.         /** Get the contained element.
  233.          * @return element contained in the node
  234.          */
  235.         public T getElement() {
  236.             return element;
  237.         }

  238.         /** Get the number of elements of the tree rooted at this node.
  239.          * @return number of elements contained in the tree rooted at this node
  240.          */
  241.         int size() {
  242.             return 1 + ((left  == null) ? 0 : left.size()) + ((right == null) ? 0 : right.size());
  243.         }

  244.         /** Get the node whose element is the smallest one in the tree
  245.          * rooted at this node.
  246.          * @return the tree node containing the smallest element in the
  247.          * tree rooted at this node or null if the tree is empty
  248.          * @see #getLargest
  249.          */
  250.         Node getSmallest() {
  251.             Node node = this;
  252.             while (node.left != null) {
  253.                 node = node.left;
  254.             }
  255.             return node;
  256.         }

  257.         /** Get the node whose element is the largest one in the tree
  258.          * rooted at this node.
  259.          * @return the tree node containing the largest element in the
  260.          * tree rooted at this node or null if the tree is empty
  261.          * @see #getSmallest
  262.          */
  263.         Node getLargest() {
  264.             Node node = this;
  265.             while (node.right != null) {
  266.                 node = node.right;
  267.             }
  268.             return node;
  269.         }

  270.         /** Get the node containing the next smaller or equal element.
  271.          * @return node containing the next smaller or equal element or
  272.          * null if there is no smaller or equal element in the tree
  273.          * @see #getNext
  274.          */
  275.         public Node getPrevious() {

  276.             if (left != null) {
  277.                 final Node node = left.getLargest();
  278.                 if (node != null) {
  279.                     return node;
  280.                 }
  281.             }

  282.             for (Node node = this; node.parent != null; node = node.parent) {
  283.                 if (node != node.parent.left) {
  284.                     return node.parent;
  285.                 }
  286.             }

  287.             return null;

  288.         }

  289.         /** Get the node containing the next larger or equal element.
  290.          * @return node containing the next larger or equal element (in
  291.          * which case the node is guaranteed not to be empty) or null if
  292.          * there is no larger or equal element in the tree
  293.          * @see #getPrevious
  294.          */
  295.         public Node getNext() {

  296.             if (right != null) {
  297.                 final Node node = right.getSmallest();
  298.                 if (node != null) {
  299.                     return node;
  300.                 }
  301.             }

  302.             for (Node node = this; node.parent != null; node = node.parent) {
  303.                 if (node != node.parent.right) {
  304.                     return node.parent;
  305.                 }
  306.             }

  307.             return null;

  308.         }

  309.         /** Insert an element in a sub-tree.
  310.          * @param newElement element to insert
  311.          * @return true if the parent tree should be re-Skew.BALANCED
  312.          */
  313.         boolean insert(final T newElement) {
  314.             if (newElement.compareTo(this.element) < 0) {
  315.                 // the inserted element is smaller than the node
  316.                 if (left == null) {
  317.                     left = new Node(newElement, this);
  318.                     return rebalanceLeftGrown();
  319.                 }
  320.                 return left.insert(newElement) ? rebalanceLeftGrown() : false;
  321.             }

  322.             // the inserted element is equal to or greater than the node
  323.             if (right == null) {
  324.                 right = new Node(newElement, this);
  325.                 return rebalanceRightGrown();
  326.             }
  327.             return right.insert(newElement) ? rebalanceRightGrown() : false;

  328.         }

  329.         /** Delete the node from the tree.
  330.          */
  331.         public void delete() {
  332.             if ((parent == null) && (left == null) && (right == null)) {
  333.                 // this was the last node, the tree is now empty
  334.                 element = null;
  335.                 top     = null;
  336.             } else {

  337.                 Node node;
  338.                 Node child;
  339.                 boolean leftShrunk;
  340.                 if ((left == null) && (right == null)) {
  341.                     node       = this;
  342.                     element    = null;
  343.                     leftShrunk = node == node.parent.left;
  344.                     child      = null;
  345.                 } else {
  346.                     node       = (left != null) ? left.getLargest() : right.getSmallest();
  347.                     element    = node.element;
  348.                     leftShrunk = node == node.parent.left;
  349.                     child      = (node.left != null) ? node.left : node.right;
  350.                 }

  351.                 node = node.parent;
  352.                 if (leftShrunk) {
  353.                     node.left = child;
  354.                 } else {
  355.                     node.right = child;
  356.                 }
  357.                 if (child != null) {
  358.                     child.parent = node;
  359.                 }

  360.                 while (leftShrunk ? node.rebalanceLeftShrunk() : node.rebalanceRightShrunk()) {
  361.                     if (node.parent == null) {
  362.                         return;
  363.                     }
  364.                     leftShrunk = node == node.parent.left;
  365.                     node = node.parent;
  366.                 }

  367.             }
  368.         }

  369.         /** Re-balance the instance as left sub-tree has grown.
  370.          * @return true if the parent tree should be reSkew.BALANCED too
  371.          */
  372.         private boolean rebalanceLeftGrown() {
  373.             switch (skew) {
  374.             case LEFT_HIGH:
  375.                 if (left.skew == Skew.LEFT_HIGH) {
  376.                     rotateCW();
  377.                     skew       = Skew.BALANCED;
  378.                     right.skew = Skew.BALANCED;
  379.                 } else {
  380.                     final Skew s = left.right.skew;
  381.                     left.rotateCCW();
  382.                     rotateCW();
  383.                     switch(s) {
  384.                     case LEFT_HIGH:
  385.                         left.skew  = Skew.BALANCED;
  386.                         right.skew = Skew.RIGHT_HIGH;
  387.                         break;
  388.                     case RIGHT_HIGH:
  389.                         left.skew  = Skew.LEFT_HIGH;
  390.                         right.skew = Skew.BALANCED;
  391.                         break;
  392.                     default:
  393.                         left.skew  = Skew.BALANCED;
  394.                         right.skew = Skew.BALANCED;
  395.                     }
  396.                     skew = Skew.BALANCED;
  397.                 }
  398.                 return false;
  399.             case RIGHT_HIGH:
  400.                 skew = Skew.BALANCED;
  401.                 return false;
  402.             default:
  403.                 skew = Skew.LEFT_HIGH;
  404.                 return true;
  405.             }
  406.         }

  407.         /** Re-balance the instance as right sub-tree has grown.
  408.          * @return true if the parent tree should be reSkew.BALANCED too
  409.          */
  410.         private boolean rebalanceRightGrown() {
  411.             switch (skew) {
  412.             case LEFT_HIGH:
  413.                 skew = Skew.BALANCED;
  414.                 return false;
  415.             case RIGHT_HIGH:
  416.                 if (right.skew == Skew.RIGHT_HIGH) {
  417.                     rotateCCW();
  418.                     skew      = Skew.BALANCED;
  419.                     left.skew = Skew.BALANCED;
  420.                 } else {
  421.                     final Skew s = right.left.skew;
  422.                     right.rotateCW();
  423.                     rotateCCW();
  424.                     switch (s) {
  425.                     case LEFT_HIGH:
  426.                         left.skew  = Skew.BALANCED;
  427.                         right.skew = Skew.RIGHT_HIGH;
  428.                         break;
  429.                     case RIGHT_HIGH:
  430.                         left.skew  = Skew.LEFT_HIGH;
  431.                         right.skew = Skew.BALANCED;
  432.                         break;
  433.                     default:
  434.                         left.skew  = Skew.BALANCED;
  435.                         right.skew = Skew.BALANCED;
  436.                     }
  437.                     skew = Skew.BALANCED;
  438.                 }
  439.                 return false;
  440.             default:
  441.                 skew = Skew.RIGHT_HIGH;
  442.                 return true;
  443.             }
  444.         }

  445.         /** Re-balance the instance as left sub-tree has shrunk.
  446.          * @return true if the parent tree should be reSkew.BALANCED too
  447.          */
  448.         private boolean rebalanceLeftShrunk() {
  449.             switch (skew) {
  450.             case LEFT_HIGH:
  451.                 skew = Skew.BALANCED;
  452.                 return true;
  453.             case RIGHT_HIGH:
  454.                 if (right.skew == Skew.RIGHT_HIGH) {
  455.                     rotateCCW();
  456.                     skew      = Skew.BALANCED;
  457.                     left.skew = Skew.BALANCED;
  458.                     return true;
  459.                 } else if (right.skew == Skew.BALANCED) {
  460.                     rotateCCW();
  461.                     skew      = Skew.LEFT_HIGH;
  462.                     left.skew = Skew.RIGHT_HIGH;
  463.                     return false;
  464.                 } else {
  465.                     final Skew s = right.left.skew;
  466.                     right.rotateCW();
  467.                     rotateCCW();
  468.                     switch (s) {
  469.                     case LEFT_HIGH:
  470.                         left.skew  = Skew.BALANCED;
  471.                         right.skew = Skew.RIGHT_HIGH;
  472.                         break;
  473.                     case RIGHT_HIGH:
  474.                         left.skew  = Skew.LEFT_HIGH;
  475.                         right.skew = Skew.BALANCED;
  476.                         break;
  477.                     default:
  478.                         left.skew  = Skew.BALANCED;
  479.                         right.skew = Skew.BALANCED;
  480.                     }
  481.                     skew = Skew.BALANCED;
  482.                     return true;
  483.                 }
  484.             default:
  485.                 skew = Skew.RIGHT_HIGH;
  486.                 return false;
  487.             }
  488.         }

  489.         /** Re-balance the instance as right sub-tree has shrunk.
  490.          * @return true if the parent tree should be reSkew.BALANCED too
  491.          */
  492.         private boolean rebalanceRightShrunk() {
  493.             switch (skew) {
  494.             case RIGHT_HIGH:
  495.                 skew = Skew.BALANCED;
  496.                 return true;
  497.             case LEFT_HIGH:
  498.                 if (left.skew == Skew.LEFT_HIGH) {
  499.                     rotateCW();
  500.                     skew       = Skew.BALANCED;
  501.                     right.skew = Skew.BALANCED;
  502.                     return true;
  503.                 } else if (left.skew == Skew.BALANCED) {
  504.                     rotateCW();
  505.                     skew       = Skew.RIGHT_HIGH;
  506.                     right.skew = Skew.LEFT_HIGH;
  507.                     return false;
  508.                 } else {
  509.                     final Skew s = left.right.skew;
  510.                     left.rotateCCW();
  511.                     rotateCW();
  512.                     switch (s) {
  513.                     case LEFT_HIGH:
  514.                         left.skew  = Skew.BALANCED;
  515.                         right.skew = Skew.RIGHT_HIGH;
  516.                         break;
  517.                     case RIGHT_HIGH:
  518.                         left.skew  = Skew.LEFT_HIGH;
  519.                         right.skew = Skew.BALANCED;
  520.                         break;
  521.                     default:
  522.                         left.skew  = Skew.BALANCED;
  523.                         right.skew = Skew.BALANCED;
  524.                     }
  525.                     skew = Skew.BALANCED;
  526.                     return true;
  527.                 }
  528.             default:
  529.                 skew = Skew.LEFT_HIGH;
  530.                 return false;
  531.             }
  532.         }

  533.         /** Perform a clockwise rotation rooted at the instance.
  534.          * <p>The skew factor are not updated by this method, they
  535.          * <em>must</em> be updated by the caller</p>
  536.          */
  537.         private void rotateCW() {

  538.             final T tmpElt       = element;
  539.             element              = left.element;
  540.             left.element         = tmpElt;

  541.             final Node tmpNode   = left;
  542.             left                 = tmpNode.left;
  543.             tmpNode.left         = tmpNode.right;
  544.             tmpNode.right        = right;
  545.             right                = tmpNode;

  546.             if (left != null) {
  547.                 left.parent = this;
  548.             }
  549.             if (right.right != null) {
  550.                 right.right.parent = right;
  551.             }

  552.         }

  553.         /** Perform a counter-clockwise rotation rooted at the instance.
  554.          * <p>The skew factor are not updated by this method, they
  555.          * <em>must</em> be updated by the caller</p>
  556.          */
  557.         private void rotateCCW() {

  558.             final T tmpElt        = element;
  559.             element               = right.element;
  560.             right.element         = tmpElt;

  561.             final Node tmpNode    = right;
  562.             right                 = tmpNode.right;
  563.             tmpNode.right         = tmpNode.left;
  564.             tmpNode.left          = left;
  565.             left                  = tmpNode;

  566.             if (right != null) {
  567.                 right.parent = this;
  568.             }
  569.             if (left.left != null) {
  570.                 left.left.parent = left;
  571.             }

  572.         }

  573.     }

  574. }