AVL树平衡旋转详解
AVL树平衡旋转详解
概述
AVL树又叫做平衡二叉树。前言部分我也有说到,AVL树的前提是二叉排序树(BST或叫做二叉查找树)。由于在生成BST树的过程中可能会出现线型树结构,比如插入的顺序是:1, 2, 3, 4, 5, 6, 7..., n。在BST树中,比较理想的状况是每个子树的左子树和右子树的高度相等,此时搜索的时间复杂度是log(N)。可是,一旦这棵树演化成了线型树的时候,这个理想的情况就不存在了,此时搜索的时间复杂度是O(N),在数据量很大的情况下,我们并不愿意看到这样的结果。
现在我们要做的事就是让BST在创建的过程中不要向线型树发展。方法就是让其在添加新节点的时候,不断调整树的平衡状态。
定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
AVL树实现
1.节点失衡
我们对于节点平衡有这样的定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。而这里提到的高度差,就是我们下面会引入的平衡因子:BF(balance factor)。
因为AVL树说到底还是一个二叉树,只有两个子节点。而且节点失衡的发生,是因为有一个新节点的插入,这个新插入的节点导致了某些节点左右子节点高度的不一致。所以我们可以枚举出以下4种情况的失衡状态。
(1)在一个节点的左子树的左子树上插入一个新节点。即LL。在这种情况下,我们可以通过将节点右旋使其平衡。如图-2所示
图-2 LL单右旋操作
原A的左孩子B变为父结点,A变为其右孩子,而原B的右子树变为A的左子树,注意旋转之后Brh是A的左子树。

(2)在一个节点的右子树的右子树上插入一个新节点。即RR。在这种情况下,我们可以通过将节点左旋使其平衡。如图-3所示;
图-3 RR单左旋操作
这时只需要把树向左旋转一次即可,如图所示,原A右孩子B变为父结点,A变为其左孩子,而原B的左子树Blh将变为A的右子树。

(3)在一个节点的左子树的右子树上插入一个新节点。即LR。在这种情况下,我们不能直接通过将节点左旋或右来使其平衡了。这里需要两步来完成,先让树中高度较低的进行一次左旋(RR型),这个时候就变成了LL了。再进行一次单右旋操作即可。如图-4所示;
图-4 LR先左旋再右旋操作
这时需要旋转两次,仅一次的旋转是不能够使二叉树再次平衡。如图所示,在B节点按照RR型向左旋转一次之后,二叉树在A节点仍然不能保持平衡,这时还需要再向右旋转一次。

(4)在一个节点的右子树的左子树上插入一个新节点。即RL。在这种情况下,我们不能直接通过将节点左旋或右来使其平衡了。这里需要两步来完成,先让树中高度较低的进行一次右旋,这个时候就变成了RR了。再进行一次单左旋操作即可。如图-5所示;
图-5 RL先右旋再左旋操作
平衡二叉树某一节点的右孩子的左子树上插入一个新的节点,使得该节点不再平衡。同样,这时需要旋转两次,旋转方向刚好同LR型相反。

从上面对节点失衡的说明,以及图解。我想你已经对旋转的操作有了一个大概地认识了吧。从图中我们也可以看出,LL型和RR型、LR型和RL型是两个行为很相似地操作。其实他们互为对称。
代码见这里
AVL树平衡旋转详解的更多相关文章
- 数据结构-AVL树的旋转
http://blog.csdn.net/GabrieL1026/article/details/6311339 平衡二叉树在进行插入操作的时候可能出现不平衡的情况,AVL树即是一种自平衡的二叉树,它 ...
- AVL树的JAVA实现及AVL树的旋转算法
1,AVL树又称平衡二叉树,它首先是一颗二叉查找树,但在二叉查找树中,某个结点的左右子树高度之差的绝对值可能会超过1,称之为不平衡.而在平衡二叉树中,任何结点的左右子树高度之差的绝对值会小于等于 1. ...
- AVL树的旋转操作详解
[0]README 0.0) 本文部分idea 转自:http://blog.csdn.net/collonn/article/details/20128205 0.1) 本文仅针对性地分析AVL树的 ...
- AVL树的旋转
平衡二叉树在进行插入操作的时候可能出现不平衡的情况,AVL树即是一种自平衡的二叉树,它通过旋转不平衡的节点来使二叉树重新保持平衡,并且查找.插入和删除操作在平均和最坏情况下时间复杂度都是O(log n ...
- AVL树的旋转实现
AVL树:带有平衡条件的二叉查找树,即一棵AVL树是其每个节点的左子树和右子树的高度最多相差1的二叉查找树.一般通过Single Rotate和Double Rotate来保持AVL树的平衡.AVL树 ...
- B树与B+详解
承接上篇SQLite采用B树结构使得SQLite内存占用资源较少,本篇将讲述B树的具体操作(建树,插入,删除等操作).在看博客时,建议拿支笔和纸,一点一点操作,毕竟知识是自己的,自己也要消化的.本篇通 ...
- P3384 【模板】树链剖分 题解&&树链剖分详解
题外话: 一道至今为止做题时间最长的题: begin at 8.30A.M 然后求助_yjk dalao后 最后一次搞取模: awsl. 正解开始: 题目链接. 树链剖分,指的是将一棵树通过两次遍历后 ...
- BIT 树状数组 详解 及 例题
(一)树状数组的概念 如果给定一个数组,要你求里面所有数的和,一般都会想到累加.但是当那个数组很大的时候,累加就显得太耗时了,时间复杂度为O(n),并且采用累加的方法还有一个局限,那就是,当修改掉数组 ...
- IOS6屏幕旋转详解(自动旋转、手动旋转、兼容IOS6之前系统)
转自 http://blog.csdn.net/zzfsuiye/article/details/8251060 概述: 在iOS6之前的版本中,通常使用 shouldAutorotateToInte ...
随机推荐
- 手机端的1px边框如何实现
(1).把边框设置为absolute,使用after,定义宽度为1px(mixin.styl) (2).通过@media,判断不同的dpi,来改变相应的Y轴宽度(base.styl),定义公共clas ...
- ie6 表格td中无内容时不显示边框的解决办法
1.在单元格中加入一个空格.这样: <td> </td> 2.直接在table里这样写:<table border="0" cellspacing=& ...
- C++ code:main参数
main函数的参数结构为两项参数: int main(int argc,char** argv){……} main的参数由操作系统传递,所以比较特殊.两个形参名一般是采用习惯名称argc和argv,表 ...
- .NetCore源码阅读笔记系列之Security (三) Authentication & AddOpenIdConnect
通过第二篇文章我们已经知道了授权的内部实现通过自定义的授权Handler来的,同样的道理 OpenIdConnect 同样是通过 OpenIdConnectHandler来请求授权的 那么它内部又是怎 ...
- [转] css自定义字体font-face的兼容和使用
@Font-face目前浏览器的兼容性: Webkit/Safari(3.2+) TrueType/OpenType TT (.ttf) .OpenType PS (.otf): Opera (10+ ...
- POJ 3259 Wormholes(bellman_ford,判断有没有负环回路)
题意:John的农场里field块地,path条路连接两块地,hole个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts.我们的任务是知道会不会在从某块地出发后又回来,看到了离开之前 ...
- BZOJ1925 [Sdoi2010]地精部落 动态规划
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1925 题意概括 给出n,n<=4200,问1~n这些数的排列中,有多少满足一下性质: 性质: ...
- 【Java】 剑指offer(9) 斐波那契数列及青蛙跳台阶问题
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项 ...
- 082 HBase的几种调优(GC策略,flush,compact,split)
一:GC的调优 1.jvm的内存 新生代:存活时间较短,一般存储刚生成的一些对象 老年代:存活时间较长,主要存储在应用程序中生命周期较长的对象 永久代:一般存储meta和class的信息 2.GC策略 ...
- 070 关于HBase的概述
1.hbase的特点 ->数据存储量可以达到亿级别数据维持在秒级 ->按列存储的数据库 ->能够存储上百万列 ->hbase的底层存储依赖于HDFS ->如何扩展hbas ...