其他分享
首页 > 其他分享> > AVL树(二叉平衡树)详解与实现

AVL树(二叉平衡树)详解与实现

作者:互联网

AVL树概念

前面学习二叉查找树二叉树的各种遍历,但是其查找效率不稳定(斜树),而二叉平衡树的用途更多。查找相比稳定很多。(欢迎关注数据结构专栏)

难点:AVL是一颗二叉排序树,用什么样的规则或者规律让它能够在复杂度不太高的情况下实现动态平衡呢?
在这里插入图片描述

不平衡概况

在这里插入图片描述
如果简单的以单节点看,大致有上面四种情形,并且他们的最后结果也是有的有所相近。只是:上下会变动。该在左面的还在左面,改在右面的还在右面
在这里插入图片描述
这只是针对在底部,对于可能出现的平衡要首先搞清楚:
在这里插入图片描述
所以针对四种不平衡,可能出现在底部,也可能出现在头,也可能出现在某个中间节点导致不平衡。 而我们只需要研究其首次不平衡点,解决之后整棵树即继续平衡。当然,在实际解决肯定会带上递归的思想解决问题。

# 四种平衡旋转方式

RR平衡旋转(左单旋转)

在这里插入图片描述
出现这种情况的原因是节点的右侧的右侧较深这时候不平衡节点需要左旋。再细看过程。

private node getRRbanlance(node oldroot) {//右右深,需要左旋
    // TODO Auto-generated method stub
    node newroot=oldroot.right;
    oldroot.right=newroot.left;
    newroot.left=oldroot;
    oldroot.height=Math.max(getHeight(oldroot.left),getHeight(oldroot.right))+1;
    newroot.height=Math.max(getHeight(newroot.left),getHeight(newroot.right))+1;//原来的root的高度需要从新计算
    return newroot;     
}

LL平衡旋转(右单旋转)

而右旋和左旋相反,但是思路相同,根据上述进行替换即可!
在这里插入图片描述
代码:

private node getLLbanlance(node oldroot) {//LL小,需要右旋转
    // TODO Auto-generated method stub
    node newroot=oldroot.left;
    oldroot.left=newroot.right;
    newroot.right=oldroot;
    oldroot.height=Math.max(getHeight(oldroot.left),getHeight(oldroot.right))+1;
    newroot.height=Math.max(getHeight(newroot.left),getHeight(newroot.right))+1;//原来的root的高度需要从新金酸  
    return newroot; 
}

RL平衡旋转(先右后左双旋转)

产生不平衡的条件原因是:

这种双旋转其实也很简单。不要被外表唬住。基于前面的单旋转,双旋转有两种具体逻辑思路
思路1:两次旋转RR,LL
在这里插入图片描述
根据上图所圈的,先对底部使得底部的大小关系变化,使其在满足二叉平衡树的条件下还满足RR结构的二叉树。所以只需要对右节点R先进行右旋,再对ROOT进行左旋即可。
思路2:直接分析
根据初始和结果的状态,然后分析各个节点变化顺序。手动操作这些节点即可!

private node getRLbanlance(node oldroot) {//右左深 
//      node newroot=oldroot.right.left;
//      oldroot.right.left=newroot.right;
//      newroot.right=oldroot.right;
//      oldroot.right=newroot.left; 
//      newroot.left=oldroot;
//      oldroot.height=Math.max(getHeight(oldroot.left),getHeight(oldroot.right))+1;
//      newroot.right.height=Math.max(getHeight(newroot.right.left),getHeight(newroot.right.right))+1;
//      newroot.height=Math.max(getHeight(oldroot.left),getHeight(newroot.right))+1;//原来的root的高度需要从新金酸  
    oldroot.right =getLLbanlance(oldroot.right);
    oldroot.height=Math.max(getHeight(oldroot.left), getHeight(oldroot.right))+1;
    return getRRbanlance(oldroot);
        
    }

LR平衡旋转(先左后右单旋转)

根据上述RL修改即可
在这里插入图片描述

private node getLRbanlance(node oldroot) {
    oldroot.left =getRRbanlance(oldroot.left);
    oldroot.height=Math.max(getHeight(oldroot.left), getHeight(oldroot.right))+1;
    return getLLbanlance(oldroot);
        
    }

java代码实现

标签:oldroot,right,newroot,getHeight,二叉,AVL,详解,节点,left
来源: https://www.cnblogs.com/bigsai/p/11407395.html