先分析排序二叉树存在的问题:
若给出一个数列{1,2,3,4,5,6},创建一颗二叉排序树(BST),存在以下问题:
1、左子树全部为空,从形式来看,更像一个单链表
2、插入速度不受影响
3、查询速度明显降低(因为需要一次比较),不能发挥BST的优势,因为每次还需要比较左子树,其查询速度比单链表还慢。
因此提出平衡二叉树的概念(AVL树)
AVL具有以下特点:它是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且左右子树都是一颗平衡二叉树,平衡二叉树的常用实现方法右红黑树、AVL树、替罪羊树、Treap、伸展树等。
举例如下:
![图片说明](https://uploadfiles.nowcoder.com/images/20200615/319217495_1592207187194_F66EBDA9885FBEB0AF205CA10B929DDE "图片标题")

二叉排序树转换成平衡二叉树的分为以下三种情况:
1、左旋转
![图片说明](https://uploadfiles.nowcoder.com/images/20200615/319217495_1592207310241_39463A6F9CFA604981F996145926D87B "图片标题")

2、右旋转
![图片说明](https://uploadfiles.nowcoder.com/images/20200615/319217495_1592207369889_AD7ECC1AB01482AFCA48AD2F94B8CEA7 "图片标题")

3、双旋转
![图片说明](https://uploadfiles.nowcoder.com/images/20200615/319217495_1592207430240_DBC9B9C8CE9AA18F5B438CB679A477C0 "图片标题")

代码实现:

public class AVLTreeDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] arr= {10,11,7,6,8,9};
        //创建一个AVLTree对象
        AVLTree avlTree=new AVLTree();
        //添加结点
        for(int i=0;i<arr.length;i++) {
            avlTree.add(new Node(arr[i]));
        }

        //遍历
        System.out.println("中序遍历");
        avlTree.infixOrder();

        System.out.println("平衡处理ing...");
        System.out.println("树的高度="+avlTree.getRoot().height());   //3
        System.out.println("树的左子树高度="+avlTree.getRoot().leftHeight());//2
        System.out.println("树的右子树高度="+avlTree.getRoot().rightHeight());//2
        System.out.println("当前的根结点="+avlTree.getRoot());//8
    }

}

class AVLTree{

    private Node root;

    public Node getRoot() {
        return root;
    }

    //public void setRoot(Node root) {
    //    this.root = root;
    //}

    //查找要删除的结点
    public Node search(int value) {
        if(root==null) {
            return null;
        }else {
            return root.search(value);
        }
    }

    //查找父节点
    public Node searchParent(int value) {
        if(root==null) {
            return null;
        }else {
            return root.searchParent(value);
        }
    }

    //1.返回的以node为根结点的二叉排序树的最小结点的值
    //2.删除node为根结点的二叉排序树的最小结点
    /**
     * 
     * @param node   传入的结点(当作二叉排序树的根结点)
     * @return    返回的以node为根结点的二叉排序树的最小结点的值
     */
    public int delRightTreeMin(Node node) {
        Node target=node;

        //循环查找左子结点,就会找到最小值
        while(target.left!=null) {
            target=target.left;
        }
        //这时target指向最小结点,删除此结点
        delNode(target.value);
        return target.value;
    }

    //编写删除结点的方法
    public void delNode(int value) {
        if(root==null) {
            return;
        }else {
            //先找到要删除的结点 targetNode
            Node targetNode=search(value);
            //如果没有找到要删除的结点
            if(targetNode==null) {
                return;
            }

            //如果我们发现当前这颗二叉排序树只有一个结点
            if(root.left==null&&root.right==null) {
                root=null;
                return;
            }

            //去找到targetNode的父节点
            Node parent=search(value);
            //如果要删除的结点是叶子节点
            if(targetNode.left==null&&targetNode.right==null) {
                //判断targetNode是父结点的左子结点,还是右子结点
                if(parent.left!=null&&parent.left.value==value) {
                    parent.left=null;
                }else if(parent.right!=null&&parent.right.value==value) {
                    parent.right=null;
                }
            }else if(targetNode.left!=null&&targetNode.right!=null) {    //删除有两颗子树的节点
                int minVal=delRightTreeMin(targetNode.right);
                targetNode.value=minVal;
            }else {  //删除只有一颗子树的结点
                //如果要删除的结点有左子结点
                if(targetNode.left!=null) {
                    if(parent!=null) {
                        //如果targetNode是parent的左子结点
                        if(parent.left.value==value) {
                            parent.left=targetNode.left;
                        }else {   //targetNode是parent的右子结点
                            parent.right=targetNode.left;
                        }
                    }else {
                        root=targetNode.left;
                    }
                }else {
                    //如果要删除的结点有右子结点
                    if(parent!=null) {
                        //如果targetNode是parent的左子结点
                        if(parent.left.value==value) {
                            parent.left=targetNode.right;
                        }else {  //如果targetNode是parent的右子结点
                            parent.right=targetNode.right;
                        }
                    }else {
                        root=targetNode.right;
                    }
                }
            }
        }
    }

    //添加节点的方法
    public void add(Node node) {
        if(root==null) {
            root=node;    //如果为空则直接让root指向node
        }else {
            root.add(node);
        }
    }

    //中序遍历
    public void infixOrder() {
        if(root!=null) {
            root.infixOrder();
        }else {
            System.out.println("二叉排序树为空,不能遍历");
        }
    }
}

//创建Node
class Node{
    int value;
    Node left;
    Node right;

    public Node(int value) {
        this.value = value;
    }

    //返回左子树的高度
    public int leftHeight() {
        if(left==null) {
            return 0;
        }
        return left.height();
    }

    //返回右子树的高度
    public int rightHeight() {
        if(right==null) {
            return 0;
        }
        return right.height();
    }

    //返回以该阶段为根结点的树的高度
    public int height() {
        return Math.max(left==null?0:left.height(), right==null?0:right.height())+1;   //+1加上结点自身的一层
    }

    //左旋转方法
    public void leftRotate() {
        //以当前根结点值创建新的结点
        Node newNode=new Node(value);
        //把新的结点的左子树设置成当前结点的左子树
        newNode.left=left;
        //把新的结点的右子树设置为当前节点的右子树的左子树
        newNode.right=right.left;
        //把当前节点的值设置为右子节点值
        value=right.value;
        //把当前节点的右子树设置成当前结点右子树的右子树
        right=right.right;
        //把当前节点的左子树设置成新的节点
        left=newNode;
    }

    //右旋转方法
    public void rightRotate() {
        //以当前根结点值创建新的结点
        Node newNode=new Node(value);
        //把新的结点的右子树设置成当前结点的右子树
        newNode.right=right;
        //把新的结点的左子树设置为当前节点的左子树的右子树
        newNode.left=left.right;
        //把当前节点的值设置为左子节点值
        value=left.value;
        //把当前节点的左子树设置成当前结点左子树的左子树
        left=left.left;
        //把当前节点的右子树设置成新的节点
        right=newNode;
    }

    //查找要删除的结点
    /**
     * 
     * @param value   希望删除的节点的值
     * @return        找到则返回该节点,否则返回null
     */
    public Node search(int value) {
        if(this.value==value) {
            return this;
        }else if(value<this.value) {    //向左子树递归查找
            //如果左子结点为空
            if(this.left==null) {
                return null;
            }
            return this.left.search(value);
        }else {                            //向右子树递归查找
            if(this.right==null) {
                return null;
            }
            return this.right.search(value);
        }
    }

    /**
     * 
     * @param value   要查找的节点
     * @return    要查找节点的父结点,找到则返回,找不到返回null
     */
    //查找要删除结点的父结点
    public Node searchParent(int value) {
        //如果当前结点就是要删除的结点的父结点,就返回
        if((this.left!=null&&this.left.value==value)||(this.right!=null&&this.right.value==value)){
            return this;
        }else {
            //如果查找的值小于当前,且左子结点不为空,则向左递归
            if(this.value>value&&this.left!=null) {
                return this.left.searchParent(value);   
            }else if(this.value<=value&&this.right!=null) {
                return this.right.searchParent(value);
            }else {
                return null;   //没有父结点
            }
        }
    }

    @Override
    public String toString() {
        return "Node [value=" + value + "]";
    }

    //添加节点的方法
    //递归的形式添加结点,注意需要满足二叉排序树的要求
    public void add(Node node) {
        if(node==null) {
            return;
        }

        //判断传入的结点的值,和当前子树的根结点的值的关系
        if(node.value<this.value) {
            //如果当前结点左子结点为null
            if(this.left==null) {
                this.left=node;
            }else {
                //递归的向左子树添加
                this.left.add(node);
            }
        }else {   //添加的结点的值大于当前结点的值
            if(this.right==null) {
                this.right=node;
            }else {
                //递归的向右子树添加
                this.right.add(node);
            }
        }

    //当添加完一个节点后,如果:(右子树的高度-左子树的高度)>1,左旋转
    if(rightHeight()-leftHeight()>1) {
        //如果它的右子树的左子树的高度大于它的右子树的右子树的高度
        if(right!=null&&right.leftHeight()>right.rightHeight()) {
            //先对右子节点进行旋转
            right.rightRotate();
            //然后再对当前节点进行左旋转
            leftRotate();
        }else {
            //直接进行左旋转
            leftRotate();
        }
        return;
    }

    //当添加完一个节点后,如果:(左子树的高度-右子树的高度)>1,右旋转
        if(leftHeight()-rightHeight()>1) {
            //如果它的左子树的右子树的高度大于它的左子树的左子树的高度
            if(left!=null&&left.rightHeight()>left.leftHeight()) {
                //先对左子节点进行左旋转
                left.leftRotate();
                //然后再对当前节点进行右旋转
                rightRotate();
            }else {
                //直接进行右旋转
                rightRotate();
            }
        }
    }
    //中序遍历
    public void infixOrder() {
        if(this.left!=null) {
            this.left.infixOrder();
        }
        System.out.println(this);
        if(this.right!=null) {
            this.right.infixOrder();
        }
    }
}