import java.nio.BufferUnderflowException;/**
* @author LongRookie
* @description: AVL ,满足平衡条件的二叉查找树
* @date 2021/6/27 16:38
*/publicclassAVL<AnyType extendsComparable<?super AnyType>>{/**
* The statement of node in AVL Tree
*
* @param <AnyType>
*/privatestaticclassAvlNode<AnyType>{//ConstructorsAvlNode(AnyType element){this(element, null, null);}AvlNode(AnyType theElement, AvlNode<AnyType> lt, AvlNode<AnyType> rt){
element = theElement;
left = lt;
right = rt;
height =0;}
AnyType element;//The data in the node
AvlNode<AnyType> left;//Left child
AvlNode<AnyType> right;//Right childint height;//Height}public AvlNode<AnyType> root;//ConstructorpublicAVL(){
root = null;}//findMaxpublic AnyType findMax(){if(isEmpty())thrownewBufferUnderflowException();returnfindMax(root).element;}//findMinpublic AnyType findMin(){if(isEmpty())thrownewBufferUnderflowException();returnfindMin(root).element;}//insertpublicvoidinsert(AnyType x){
root =insert(x, root);}//removepublicvoidremove(AnyType x){
root =remove(x,root);}//containpublicbooleancontains(AnyType x){returncontains(x,root);}privatebooleancontains(AnyType x, AvlNode<AnyType> t){if(t == null){returnfalse;}int compareResult = x.compareTo(t.element);if(compareResult <0){returncontains(x, t.left);}elseif(compareResult >0){returncontains(x, t.right);}else{returntrue;}}privatebooleanisEmpty(){return root == null;}private AvlNode<AnyType>insert(AnyType x, AvlNode<AnyType> t){if(t == null){returnnewAvlNode<AnyType>(x);}int compareResult = x.compareTo(t.element);if(compareResult <0){
t.left =insert(x, t.left);}elseif(compareResult >0){
t.right =insert(x, t.right);}else;//Duplicate; do nothingreturn t;}privatestaticfinalint ALLOWED_IMBALANCE =1;/**
* Assume t is either balanced or within one of being balanced
*
* @param t
* @return
*/private AvlNode<AnyType>balance(AvlNode<AnyType> t){// useless in insert operation;if(t == null){return t;}// if the height of subtree t is larger than that of right subtree;if(height(t.left)-height(t.right)> ALLOWED_IMBALANCE){// notice the '=' calculation ,when only insert ,that is useless;// when remove,that is possibly useful;if(height(t.left.left)>=height(t.left.right)){
t =rotateWithLeftChild(t);}else{
t =doubleWithLeftChild(t);}}elseif(height(t.right)-height(t.left)> ALLOWED_IMBALANCE){if(height(t.right.right)>=height(t.right.left)){
t =rotateWithRightChild(t);}else{
t =doubleWithRightChild(t);}}//update the height, the operate is useful for the node that does not need to balance;
t.height = Math.max(height(t.left),height(t.right))+1;return t;}/**
* Rotate binary tree node with left child
* For AVL trees ,this is a single rotation for case 1
* Update heights ,then return new root
*
* @param k2
* @return
*/private AvlNode<AnyType>rotateWithLeftChild(AvlNode<AnyType> k2){
AvlNode<AnyType> k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max(height(k2.left),height(k2.right))+1;
k1.height = Math.max(height(k1.left),height(k1.right))+1;return k1;}/**
* Rotate binary tree node with right child
* For AVL trees ,this is a single rotation for case 4
* Update heights ,then return new root
*
* @param k1
* @return
*/private AvlNode<AnyType>rotateWithRightChild(AvlNode<AnyType> k1){
AvlNode<AnyType> k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max(height(k1.left),height(k1.right))+1;
k2.height = Math.max(height(k2.left),height(k2.right))+1;return k2;}/**
* Double rotate binary tree node;first left child
* with its right child; then node k3 with new left child.
* For AVL trees, this is a double rotation for case 2.
* Update heights , then return new root.
*
* @param k3
* @return
*/private AvlNode<AnyType>doubleWithLeftChild(AvlNode<AnyType> k3){
k3.left =rotateWithRightChild(k3.left);returnrotateWithLeftChild(k3);}/**
* Double rotate binary tree node;first right child
* with its left child; then node k3 with new right child.
* For AVL trees, this is a double rotation for case 3.
* Update heights , then return new root.
*
* @param k3
* @return
*/private AvlNode<AnyType>doubleWithRightChild(AvlNode<AnyType> k3){
k3.right =rotateWithLeftChild(k3.right);returnrotateWithRightChild(k3);}/**
* Return the height of node t, or -1, if null;
*
* @param t node
* @return
*/privateintheight(AvlNode<AnyType> t){return t == null ?-1: t.height;}/**
* Internal method to find the node containing the smallest item in a subtree
*
* @param t the node that roots the subtree
* @return the node containing the smallest item
*/private AvlNode<AnyType>findMin(AvlNode<AnyType> t){if(t == null){return null;}if(t.left == null){return t;}returnfindMin(t.left);}/**
* Internal method to find the node containing the largest item in a subtree
*
* @param t the node that roots the subtree
* @return the node containing the largest item
*/private AvlNode<AnyType>findMax(AvlNode<AnyType> t){if(t == null){return null;}if(t.right == null){return t;}returnfindMax(t.right);}private AvlNode<AnyType>remove(AnyType x, AvlNode<AnyType> t){if(t == null){return t;// Item not found; do nothing}int compareResult = x.compareTo(t.element);if(compareResult <0){
t.left =remove(x, t.left);}elseif(compareResult >0){
t.right =remove(x, t.right);}elseif(t.left != null && t.right != null){//Two children
t.element =findMin(t.right).element;//the smallest item in right subtree
t.right =remove(t.element, t.right);}else
t =(t.left != null)? t.left : t.right;returnbalance(t);}}