Live2D

平衡二叉树(AVL树)

为什么要在二叉搜索树的基础上提出平衡二叉树?

考虑这样一种情况:

当我们的二叉搜索树结构如图所示时,

这棵树与单链表的查找,删除时间复杂度相比相差无几,甚至高于单链表(二叉搜索树还需要判断左子树)

为了避免上述不平衡的存储结构出现

以及保证较高的查询效率,提出了平衡二叉树

平衡二叉树定义:任意节点的子树的高度差都小于等于1

基于Java实现平衡二叉搜索树(AVL树)

为了减少文章篇幅,本文基于上篇博客的二叉树代码完成AVL树的构建,并主要讲解平衡二叉树的旋转问题。

关于二叉排序树的详细构建,代码见:二叉排序树

首先实现getHeight方法得到当前树的高度和其子树的高度:

 

//返回根结点的高度
    public int height(){
        return Math.max(left == null ? 0 : left.height(),right == null ? 0 : right.height())+1;
    }

 

递归思想解释:以根结点左结点和右节点为初始递归条件,一直往下递归到叶子结点,往上每返回一层递归函数高度加一,比较左右结点路径的深度,得到最大深度

 

 

 

 

 

 

 获得当前结点的左子结点和右子结点深度的思想类似:

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

接着考虑一般情况下的左旋和右旋情形:

左旋:该树满足所有结点的右侧树高度均大于左侧树高度

由于右边比左边高,所以很容易想到将根节点从5移动到8,对结点8周围的三条连接线做处理,为了满足二叉树的定义,

将6接到结点5上。而此时如果为了得到高度相同的左右子树而直接修改根节点,会涉及到大量的修改。

所以为了方便起见,在右树中删除一个结点,在左树中添加一个结点

 

 左旋代码实现:

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;
    }

接着考虑双旋转问题的解决:

 

 此时通过单次左旋无法使树恢复平衡状态,可以单看结点11,结点11的左子树高度为2,右子树为0,刚好与整体树失衡的方向相反,

那么我们对结点11做一次右旋再对树整体做一次左旋即可完成平衡二叉树的构建。

if(rightHeight()-LeftHight() > 1){
            if(left != null && left.LeftHight() > left.rightHeight()){
                left.rightRotate();
                leftRotate();
            }else {
                leftRotate();
            }
        }

对以上方法进行总结,并将其添加到add方法中:因为每添加一个新数据就需要判断树当前是否失衡。

整体add方法如下:

public void add(Node node){
        if(node == null){
            return;
        }
        if(this.value > node.value){
            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);
            }
        }
        //右旋
        if(LeftHight()-rightHeight() > 1){
            if(right != null && left.rightHeight() > left.LeftHight()){
                left.leftRotate();
                rightRotate();
            }else {
                rightRotate();
            }
            return;
        }
        //左旋
        if(rightHeight()-LeftHight() > 1){
            if(left != null && left.LeftHight() > left.rightHeight()){
                left.rightRotate();
                leftRotate();
            }else {
                leftRotate();
            }
        }
    }

 

posted @ 2020-11-04 22:13  eminemrapgod  阅读(150)  评论(0编辑  收藏  举报