红黑树的删除调整过程(转载)

首先简单描述一下二叉搜索树的删除过程,可以分为以下四种情况

  1. 要删除的节点没有左右孩子
  2. 要删除的节点只有左孩子
  3. 要删除的节点只有右孩子
  4. 要删除的节点有左右孩子

对于第一种情况,直接删除。

如果要删除的节点只有左孩子,那么就让该节点的父亲结点指向该节点的左孩子,然后删除该节点,返回true;
1666300-20190715084440600-1001038410.png

如果要删除的节点只有右孩子,那么就让该节点的父亲结点指向该节点的右孩子,然后删除该节点,返回true;
1666300-20190715084457422-810726864.png

对于上面这两种情况我们还应该在之前进行一个判断,就是判断这个节点是否是根节点,如果是根节点的话,就直接让根节点指向这个节点的左孩子或右孩子,然后删除这个节点。

最后一种也是最麻烦的一种就是要删除的节点的左右孩子都存在。此时我们的删除方法如下:

  1. 找到该节点的右子树中的最左孩子(也就是右子树中序遍历的第一个节点)

  2. 把它的值和要删除的节点的值进行交换

  3. 然后删除这个节点即相当于把我们想删除的节点删除了,返回true;
    1666300-20190715084513932-1526938341.png

对于红黑树的删除操作,是在上述操作的基础上对删除节点后的红黑树进行调整。我们按照被删除节点的颜色不同进行讨论。

要删除的节点为红色节点

  1. 删除红色的叶子节点(D表示待删除的节点,P表示其父亲节点)

    img

    img
    直接删除即可

  2. 删除红色的非叶节点

    只可能出现被删除的节点左右子树都存在的情况,否则违背红黑树的性质。对于这种情况,我们只需要找到被删除节点的直接后继,用它的值取代被删除节点的值,然后按情况1删除。

要删除的节点为黑色节点

  1. 删除黑色的叶子节点

    情况1:待删除节点D的兄弟节点S为红色

    D是左节点的情况

    img

    调整做法是将父亲节点和兄弟节点的颜色互换,也就是p变成红色,S变成黑色,然后将P树进行AVL树种的RR型操作,结果如下图

    img

    这个时候我们会发现,D的兄弟节点变成了黑色,这样就成后面要讨论的情况。

    D是右节点的情况

    img

    将P和S的颜色互换,也就是将P变成红色,将S变成黑色,然后对P进行类似AVL树的LL操作。结果如下图:

    img

    此时D的兄弟节点变成了黑色,这样就成了我们后面要讨论的情况

    情况2:兄弟节点为黑色,且远侄子节点为红色。

    D为左孩子对的情况,这时D的远侄子节点为S的右孩子

    img

    没有上色的节点表示黑色红色均可,注意如果SL为黑色,则SL必为NULL节点。

    这个时候,如果我们删除D,这样经过D的子节点(NULL节点)的路径的黑色节点个数就会减1,但是我们看到S的孩子中有红色的节点,如果我们能把这棵红色的节点移动到左侧,并把它改成黑色,那么就满足要求了,这也是为什么P的颜色无关,因为调整过程只在P整棵子树的内部进行。

    调整过程为,将P和S的颜色对调,然后对P树进行类似AVL树RR型的操作,最后把SR节点变成黑色,并删除D即可。

    img

    D为右孩子的情况,此时D的远侄子为S的左孩子

    img

    同样,将P和S的颜色对调,然后再对P树进行类似AVL树RL型的操作,最后将SR变成黑色,并删掉D即可。结果如下图:

    img

    情况3:兄弟节点S为黑色,远侄子节点为黑色,近侄子节点为红色

    D为左孩子的情况,此时近侄子节点为S的左孩子

    img

    做法是,将SL右旋,并将S和SL的颜色互换,这个时候就变成了情况4。

    img

    D为右孩子的情况,此时近侄子节点为S的右孩子

    img

    做法是将S和SR颜色对调,然后对SR进行左旋操作,这样就变成了情况4,结果如下图:

    img

    情况4:父亲节p为红色,兄弟节点和兄弟节点的两个孩子(只能是NULL节点)都为黑色的情况。

    img

    如果删除D,那经过P到D的子节点NULL的路径上黑色就少了一个,这个时候我们可以把P变成黑色,这样删除D后经过D子节点(NULL节点)路径上的黑色节点就和原来一样了。但是这样会导致经过S的子节点(NULL节点)的路径上的黑色节点数增加一个,所以这个时候可以再将S节点变成红色,这样路径上的黑色节点数就和原来一样啦!

    所以做法是,将父亲节点P改成黑色,将兄弟节点S改成红色,然后删除D即可。如下图:

    img

    情况5:父亲节点p,兄弟节点s和兄弟节点的两个孩子(只能为NULL节点)都为黑色的情况

    img

    方法是将兄弟节点S的颜色改成红色,这样删除D后P的左右两支的黑节点数就相等了,但是经过P的路径上的黑色节点数会少1,这个时候,我们再以P为起始点,继续根据情况进行平衡操作(这句话的意思就是把P当成D(只是不要再删除P了),再看是那种情况,再进行对应的调整,这样一直向上,直到新的起始点为根节点)。结果如下图:

  2. 删除黑色的非叶节点

    • 删除的黑色节点左右子树都存在

      首先找到被删除元素D的直接后继,用直接后继的值替换D的值,再对直接后继进行删除。我们可以知道,直接后继是不可能左右子树都存在的,这样就可以将左右子树都存在的情况转化为下面的情况。

    • 删除的黑色节点仅有左子树或者仅有右子树。

      在红黑树中只存在下面这几种情况,其中黑色的竖线代替了左右分支的情况

      img

      img

这两种的处理方式是一样的,即用D的左孩子或者右孩子替换D,并DR的颜色改成黑色即可。

转载自:https://www.cnblogs.com/qingergege/p/7351659.htmlhttps://www.cnblogs.com/MrListening/p/5782752.html

转载于:https://www.cnblogs.com/gcheeze/p/11186806.html

### 关于 UniApp 框架推荐资源与教程 #### 1. **Uniapp 官方文档** 官方文档是最权威的学习资料之一,涵盖了从基础概念到高级特性的全方位讲解。对于初学者来说,这是了解 UniApp 架构技术细节的最佳起点[^3]。 #### 2. **《Uniapp 从入门到精通:案例分析与最佳实践》** 该文章提供了系统的知识体系,帮助开发者掌握 Uniapp 的基础知识、实际应用以及开发过程中的最佳实践方法。它不仅适合新手快速上手,也能够为有经验的开发者提供深入的技术指导[^1]。 #### 3. **ThorUI-uniapp 开源项目教程** 这是一个专注于 UI 组件库设计实现的教学材料,基于 ThorUI 提供了一系列实用的功能模块。通过学习此开源项目的具体实现方式,可以更好地理解如何高效构建美观且一致的应用界面[^2]。 #### 4. **跨平台开发利器:UniApp 全面解析与实践指南** 这篇文章按照章节形式详细阐述了 UniApp 的各个方面,包括但不限于其工作原理、技术栈介绍、开发环境配置等内容,并附带丰富的实例演示来辅助说明理论知识点。 以下是几个重要的主题摘选: - **核心特性解析**:解释了跨端运行机制、底层架构组成及其主要功能特点。 - **开发实践指南**:给出了具体的页面编写样例代码,展示了不同设备间 API 调用的方法论。 - **性能优化建议**:针对启动时间缩短、图形绘制效率提升等方面提出了可行策略。 ```javascript // 示例代码片段展示条件编译语法 export default { methods: { showPlatform() { console.log(process.env.UNI_PLATFORM); // 输出当前平台名称 #ifdef APP-PLUS console.log('Running on App'); #endif #ifdef H5 console.log('Running on Web'); #endif } } } ``` #### 5. **其他补充资源** 除了上述提到的内容外,还有许多在线课程视频可供选择,比如 Bilibili 上的一些免费系列讲座;另外 GitHub GitCode 平台上也有不少优质的社区贡献作品值得借鉴研究。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值