上一篇我们聊过,二叉查找树不是严格的O(logN),如果找到一种方法,使得二叉查找树不受输入序列和插入结点等的影响,始终保持平衡状态,从而达到很好的检索效率.平衡二叉树就是基于此目的而产生的.
定义:平衡二叉树或为空树,或为如下性质的二叉排序树(平衡二叉树是一种特殊的二叉排序树):
(1)左右子树深度之差的绝对值不超过1;
(2)左右子树仍然为平衡二叉树.
平衡因子BF=左子树深度-右子树深度.
平衡二叉树每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。
如图所示为平衡树和非平衡树示意图:
显然,如果有n个结点,则他的高度为O(logN),因而在其上进行的各种操作,都只需要O(logN)的时间代价.但问题在于如何保持一颗avl树的结构,使得对他的任何操作,都不改变他的平衡特性.实际上,主要是通过旋转的局部操作来调整使其保持平衡特性.
旋转
左旋:
对x进行左旋,意味着”将x变成一个左节点”。
右旋:
对y进行右旋,意味着”将y变成一个右节点”。
结点再怎么失衡都逃不过4种情况,下面我们来看一下怎么对这4中情况进行对应的旋转。
<1>.LL型平衡旋转法 —- 右旋
我们看到,在向树中追加“节点1”的时候,根据定义我们知道这样会导致了“节点3”失衡,可以这样想,把这棵树比作齿轮,我们在“节点5”处把齿轮往下拉一个位置,也就变成了后面这样“平衡”的形式.
<2>.RR型平衡旋转法 —- 左旋
同样,”节点5“满足”RR型“,其实我们也看到,这两种情况是一种镜像,当然操作方式也大同小异,我们在”节点1“的地方将树往下拉一位,最后也就形成了我们希望的平衡效果。
<3>.LR型平衡旋转法 —- 左右旋
从图中我们可以看到,当我们插入”节点3“时,“节点5”处失衡,注意,找到”失衡点“是非常重要的,当面对”LR型“时,我们将失衡点的左子树进行”RR型左旋转”,然后进行”LL型右旋转“,经过这样两次的旋转就OK了,很有意思,对吧。
<4>.RL型平衡旋转法 —- 右左旋
这种情况和“情景3”也是一种镜像关系,很简单,我们找到了”节点15“是失衡点,然后我们将”节点15“的右子树进行”LL型右旋转“,然后进行”RR型左旋转“,最终得到了我们满意的平衡。
插入
如果我们理解了上面的这几种旋转,那么添加方法简直是轻而易举,出现了哪一种情况调用哪一种旋转方法而已。
删除
同理,删除也是.