平衡二叉树(AVL)插入、删除详解——基于树的查找(二)

由上节内容二叉排序树可知:

  1. 二叉排序树在最好的情况下只需O(logn)的时间代价;
  2. 但在最差情况下会蜕化为线性查找的时间复杂度O(n);

造成原因:这种情况主要是由于二叉排序树中结点分布不均衡导致,可能是二叉排序树在建立时由于输入序列造成的,也可能是由于在树中不断插入结点而造成的。
解决想法:如果能够找到一种方法,使得二叉排序树不受输入序列或插入结点等的影响,始终保持平衡状态,从而达到很好的检索效率。
解决方案:平衡二叉树(AVL)。

平衡二叉树

基于上述目的,Adelson-Velskii和Landis发明出平衡二叉树(AVL)。它是满足以下性质的特殊的二叉排序树。
平衡二叉树或者是一棵空树;或者是具有如下特性的二叉排序树:

  1. 二叉排序树中任何一个结点的左子树或右子树高度相差的绝对值最多为1;
  2. 它的左、右子树也分别都是平衡二叉树。

为了方便描述,在此引入平衡因子(Balance Factor)的概念。
用BF(Node)表示结点Node的平衡因子,显然,BF(Node)= Node的右子树高度 – Node的左子树高度。

如图1所示为带平衡因子的AVL树,而图2不是AVL树,BF(30) = 2不满足条件。
《平衡二叉树(AVL)插入、删除详解——基于树的查找(二)》
显然,满足条件的一棵AVL,如果含有n个结点,则它的高度为O(logn),因而在其上进行的各种操作,例如查找、插入、删除等,都只需要O(logn)的实际复杂度。
问题主要在于:如何保持一棵AVL树的结构,使得不论对其进行何种操作,都不改变它的平衡特性?
解决方法:当一棵AVL因为某操作破坏了平衡特性后,通过旋转的局部操作来调整,使其保持平衡特性。

AVL的插入

方法:首先在AVL树中查找插入位置,将新结点插入,查找需要调整的最小子树,记录新结点的双亲结点,即新插入的结点为孩子结点,然后修改双亲结点的BF。

  1. 如果BF(双亲结点) == 0,则插入成功,AVL平衡特性没有被破坏,直接返回;
  2. 如果BF(双亲结点) == 1 || BF(双亲结点) == -1,则孩子结点和双亲结点都向根结点移动一步,修改双亲结点的BF,继续判断,循环执行,直至双亲结点为空,返回;
  3. 如果BF(双亲结点) == 2 || BF(双亲结点) == -2,则找到了失衡的最小子树,通过旋转调整该子树,使其恢复平衡,然后返回。

在一棵AVL中插入一个新结点时,情况类似于二叉排序树的插入,新结点将出现在查找失败的位置,即作为一个新的叶子结点插入该位置。此时,整棵树可能发生以下4种失衡的情况:

(1)LL型:

《平衡二叉树(AVL)插入、删除详解——基于树的查找(二)》
插入位置为AVL的左子树的左子树导致的不平衡。
失衡特点:BF(A)= -2,BF(B) = -1。
调整方案:左单旋转:以B为轴,对A做一次顺时针旋转,将A作为Br,将原来的Br作为Al。

(2)LR型:

插入位置为AVL的左子树的右子树时导致的不平衡。
失衡特点:BF(A) = -2,BF(B) = 1。
《平衡二叉树(AVL)插入、删除详解——基于树的查找(二)》

(3)RR型:

与LL型对称。
插入位置为AVL的右子树的右子树导致的不平衡。
失衡特点:BF(A)= 2,BF(B) = 1。
调整方案:右单旋转。
《平衡二叉树(AVL)插入、删除详解——基于树的查找(二)》

(4)RL型:

插入位置为AVL的右子树的左子树时导致的不平衡。
失衡特点:BF(A) = 2,BF(B) = -1。
《平衡二叉树(AVL)插入、删除详解——基于树的查找(二)》

AVL的删除

方法:首先在AVL中确定要删除的结点的位置,删除结点的算法参考二叉排序树中删除结点的算法思想(类似)。关键在于删除后修改BF并找出失衡的子树。
删除一个结点后,修改其双亲的BF,判断以其双亲结点的子树是否失衡,

  1. 如果失衡,则通过对该子树旋转进行调整,使其恢复平衡,然后向根结点追溯,循环执行;
  2. 如果没有失衡,直接向根结点追溯,循环执行;
  3. 直到所有结点的BF都符合定义,然后返回。

具体分2种情况讨论。

(1)当BF(待删结点的双亲) == 0。

则其BF改为1或-1。由于以待删结点的双亲为根的整棵子树高度未变,不会影响到上层结点,则调整可以结束。

(2)当BF(待删结点的双亲) == 1 || BF(删除结点的双亲) == -1。

此时也分两张情况:

  1. 删除较高子树的结点:较高子树高度缩短,BF修改为0,需要继续向上修改。
  2. 删除较低子树的结点:较低子树高度缩短,必然失衡,则会出现3种情况:
    (1)如果BF(较高子树根结点) == 0,执行单旋转(LL或RR)恢复平衡,可以停止;
    (2)如果BF(待删结点的双亲) == BF(较高子树根结点),执行单旋转(LL或RR)恢复平衡,继续向上回溯;
    (3)如果BF(待删结点的双亲) == -BF(较高子树根结点),即BF相反,执行一个双旋转(LR或RL)恢复平衡,继续向上回溯。

效率

由于具有n个结点的平衡二叉树的高度为O(logn),因而查找、插入、删除效率都是O(logn),而且都是从根到叶子结点单路径进行的局部运算。
Linux采用AVL描述进程的虚拟内存段。

上一篇:二叉排序树
下一篇:红黑树

参考资料:《数据结构与算法》 王曙燕 主编 王春梅 副主编 人民邮电出版社

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/weixin_39651041/article/details/80035950
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞