本篇主要衔接上一次对王道数据结构中, 平衡二叉树的插入操作(LL/RR/LR/RL)的个人理解, 对平衡二叉树的删除给出了一些个人的理解方法, 仅供"道友"进行参考和交流
如果你对我在本文中提及的"摆下来"这个概念, 或是RL=LL+RR的说法不理解, 请参考我的上一篇博文, 在那里我很详细地阐述了这种思考方式: 平衡二叉树的插入操作的理解方法
那么开始本文的内容 😃
意义
首先, 为什么要对平衡二叉树的删除进行专门的探讨呢?
答曰: 与平衡二叉树的插入同理, 当删除某个节点后,
- 需要保持二叉排序树的性质不变(左<中<右);
- 并且如果删除节点后导致平衡二叉树出现了不平衡, 则同样需要对其进行调整
此时, 请先行回忆一下二叉排序树的删除:
步骤
以上, 是王道给出的, 平衡二叉树的删除操作的方法
我在下面将通过几个例子, 解释王道的方法, 以及我个人处理此类问题的思考方式
例一
-
删除节点: 现在对55节点进行删除, 其是叶子结点, 直接删除
-
找最小不平衡子树: 删除后, 向上找最小不平衡子树, 发现自下往上直到75, 其不平衡因子为2, 故以75为根的子树就是最小不平衡子树
-
找儿孙节点:
依照王道的方法, 要在75节点下, 选择其个头高的儿子和孙子, 以确定要进行的调整是哪种类型(LL/RR/LR/RL)
如上图中, 个头最高的儿子是右子树, 于是R_, 个头最高的孙子还是右子树, 于是RR, 即要使用RR操作进行平衡调整我个人对上述方法不是很推荐, 没有必要这样把简单问题搞复杂
我的理解: 直接对当前的75子树进行分析, 其形态相当于在90号节点进行了插入(90号的左右插入无影响), 即相当于对75树进行了RR插入 -
根据孙子的位置调整平衡:
这里王道的方法是根据子孙的位置, 选择相关操作, 叙述起来转来转去很麻烦我的理解: 之前已经将这个删除问题转化成为了对75树进行了RR插入的问题, 于是直接对75树进行RR操作调整即可(75摆下来砸掉80的左子树, 捡起来装在75的右子树上, 80作为新子树的根节点)
[不理解我的"摆下来""砸掉"等叙述方式的同学可以移步文章开头的链接]调整结果如下图所示:
-
检查不平衡是否向上传导了:
接下来, 由于我们进行了RR操作, 将75树调整为80树后, 其高度从原先的4降为了3, 这就会对上面的节点的平衡因子产生影响, 有可能使得上面的某个节点的平衡因子>1, 因此需要检查上面节点的balance值
本例中, 检查50号节点, 其保持平衡, 故本次操作完成
下面将给出一系列例子对我的理解方法进行进一步阐述
例二
现在删除32号节点, 向上观察, 发现44号节点的balance值为2, 即44树为最小不平衡子树
对于44树, 删除操作相当于对其右子树78的左子树50进行了插入, 明显为RL插入, 于是将本次删除问题转化为了对44的RL插入调整问题
于是对44树进行RL操作, 即RL=LL+RR, LL: 先把78摆下来, 作为50的右子树, 50作为根节点, RR: 再把44摆下来, 作为50的左子树, 50替代44的位置, 完成RL操作
[不理解’RL=LL+RR"“摆下来”"砸掉"等叙述方式的同学可以移步文章开头的链接]
明显50已经是最顶端了, 其上面没有节点了, 故操作结束
例三
现在要删除32号节点, 可以看出, 就是把例二的树作为一个子树放进更大的树里, 进行操作调整后如下图:
可以看到, 操作后50树平衡了, 但其上方的33节点的balance值变成了2, 即出现了新的不平衡, 此时要对33树进行调整:
观察发现, 可以将33树调整问题转化为33树的LR插入问题, 于是LR=RR+LL
RR: 将10摆下来作为20的左子树, 20替代10的位置;
LL: 再将33摆下来作为20的右子树, 20作为新的根结点, 操作完后如下图:
此时20上面没有节点了, 于是完成操作
例四
此时删除75节点, 75节点左右子树都有, 于是要么用75的前驱60替换掉75, 要么用其后继77替换掉75, 这里我们选用60(如果用77, 则80会不平衡, 还需调整, 后面将给出方案)
删除后新的树如下图:
不难看出, 60节点不平衡, 其相当于对60节点进行了RR插入, 于是我们对60进行RR操作
将60摆下来作为80的左子树, 80的左子树作为60的右子树, 80作为调整后的根节点, 调整好后如下图
调整后检查其上方的50节点, 其仍然平衡, 于是调整结束
如果之前用77替代, 则有一个问题:
对于80树, 其可以被理解为对80的RR插入, 也可以理解为RL插入
如果使用王道的"找儿子孙子个头法", 会发现左右孙子的个头一样高
如果进行RR调整, 结果如下:
如果用RL调整, RL=LL+RR
即90摆下来作为85的右子树, 再把80摆下来作为85的左子树, 结果如下图
两种操作的祖先节点都是平衡的, 无需再调整
可以看到, 两种操作, 最终产生的平衡二叉树形态不一样,但都符合平衡二叉树的特性, 也符合二叉排序树的特性
注: 平衡二叉树的删除操作的时间复杂度为 O(log2n) n为结点个数
总结
本文主要通过几个例子, 对王道给出的平衡二叉树的删除操作进行了讲解, 同时给出了我个人对于此类问题的解决方法, 如有问题, 还请不吝批评指正 😃