AVL树的旋转图解和简单实现

平衡条件
一个最理想的平衡条件是左右两个子树的高度完全相等,但只有节点数量为2^n-1的树才满足这个条件(n是层数,2层要3个,3层要7个)。这个条件太严格,不好用。

如果只要求根节点平衡的话,上面的条件可能会容易实现一点,但是会出现下面这样坏的二叉树: 


因此一颗AVL树的条件是,对于每个节点来说,这个节点的左右子树的高度最多差1.

简单示例
AVL树: 

这里写图片描述
非AVL二叉树: 


这里写图片描述
旋转
在每一次插入数值之后,树的平衡性都可能被破坏,这时可以通过一个简单的操作来矫正平衡–旋转。

旋转的目的就是减少高度,通过降低整棵树的高度来平衡。哪边的树高,就把那边的树向上旋转。

通过旋转可以降低高度。

所谓的左旋和右旋都是以子树为原点的:如b是a的子树,那么旋转就围绕b来进行。
如果b是a的左子树,那么就围绕b将a向右旋转,看着就像是a直接掉下来了,掉成了b的右子树。
如果b是a的右子树,那么就围绕b将a向左旋转,看着就像是a直接掉下来了,掉成了b的左子树。
插入节点时分四种情况,四种情况对应的旋转方法是不同的:

例如对于被破坏平衡的节点 a 来说:

插入方式    描述    旋转方式
LL    在a的左子树根节点的左子树上插入节点而破坏平衡    右旋转
RR    在a的右子树根节点的右子树上插入节点而破坏平衡    左旋转
LR    在a的左子树根节点的右子树上插入节点而破坏平衡    先左旋后右旋
RL    在a的右子树根节点的左子树上插入节点而破坏平衡    先右旋后左旋
1.LL 右旋转
就拿最简单的举例了。

一个简单的AVL树: 

这里写图片描述

这时是平衡的,如果在插入一

这时是平衡的,如果在插入一个元素3,就会变成下面这样,破坏平衡: 

这里写图片描述
被破坏了平衡首先要找到是哪个树被破坏了平衡,然后调整这个树。然后继续往上一个一个的调整。

既然是被新插入的节点3破坏的,那么不平衡的树一定在从新插入的节点3到根节点8的路径上。找离新插入的节点最近的不平衡的树进行调整,上图中就是7.

节点7的左子树 高度为1,右子树为空,高度为-1 ,不平衡。根据表格要进行右旋转。

先把7这颗不平衡的树挑出来: 

这里写图片描述
这棵树是最近的不平衡的树,7的左子树5高度为1,右子树为空,所以右子树高度是-1.两者的高度差达到了2,超过了1.

因为左子树5的高度更高,所以要把左子树5向上提一下,这时旋转就很明显了,抓着5向上一提,7就掉到5的右边了,成了5的右子树。

这个过程就是右旋: 

这里写图片描述
这时继续往上找,发现每个节点都符合了平衡条件,所以整棵树就变成了AVL树。

那如果节点5本来就有了右子树呢?照样右旋转,只要把原来5的右子树变成旋转后的7的左子树就行了。因为5的右子树肯定比5大,但是也肯定比7小的: 

这里写图片描述
其实上面最后旋转成的树是下面这样的: 

这里写图片描述
这棵树的根节点是不平衡的,还需要使用后面的双旋转来调整。

使用LR先左旋后右旋调整后是这样的,具体方法看后面的: 

这里写图片描述
2. RR 左旋转
在右子树的右子树上插入节点破坏的平衡需要左旋转来矫正。

左旋转和右旋转类似,都是单旋转,给个流程图。 

这里写图片描述
3. LR 先左旋再右旋
如果在第一个例子中插入的不是3,而是6,就成了下面的样子,依然说破坏了平衡 

这里写图片描述
被破坏平衡的树依然是7,但是这次就不能通过一次旋转解决了,咋转都不行。

要从6开始到7进行先左旋再右旋才可以矫正平衡: 


这里写图片描述
4. RL 先右旋再左旋
当破坏平衡的节点是这个树的右子树的左子树时,要进行先右旋转再左旋转来矫正。

同样是从破坏平衡的那个节点开始旋转,先右旋转后左旋转: 


这里写图片描述

代码实现:

 

--------------------- 
作者:喵了个呜s 
来源:CSDN 
原文:https://blog.csdn.net/qq_25806863/article/details/74755131 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值