C++ STL(第十三篇:RB-tree)

本文详细介绍了C++ STL中的RB-tree(红黑树)概念,包括其插入节点的操作、节点设计、迭代器、数据结构以及元素操作。红黑树是一种平衡二叉搜索树,遵循特定的着色规则。文章通过实例阐述了插入新节点可能导致的四种情况及其解决策略,探讨了RB-tree的调整和旋转操作,以保持树的平衡。此外,还讨论了RB-tree的迭代器特性和数据结构设计,以及元素的搜索方法。
摘要由CSDN通过智能技术生成

1、概述

RB-tree(红黑树) 是除了 AVL-tree 之外,另一个被广泛使用的平衡二叉搜索树。所谓 RB-tree,不仅是一个二叉搜索树,而且必须满足以下规则:
1、每个节点不是红色就是黑色。
2、根节点为黑色。
3、如果节点为红,其子节点必须为黑。
4、任一节点至NULL(树尾端)的任何路径,所含之黑节点数必须相同。

根据规则4,新增节点必须为红;根据规则3,新增节点之父节点必须为黑。当新节点根据二叉搜索树的规则达到其插入点,却未能符合上述条件时就必须调整颜色并旋转树形

在这里插入图片描述

2、插入节点操作前述

假设我们在上图所示的 RB-tree 中分别插入 3,8,35,75,根据二叉搜索树的规则,这四个新节点的落脚处应该如下图所示:
在这里插入图片描述他们都破坏了 RB-tree 的规则,因此我们必须调整树形,也就是旋转树形并改变节点颜色。

为了方便讨论,这里整理一些代名词。
X:新节点,P:父节点,G:祖父节点,S:伯父节点,GG:曾祖父节点

根据二叉搜索树的规则,新节点 X 必为叶节点。根据红黑树的规则 4,X 必为红。
若此时 P 亦为红(这就违反了规则 3,必须调整树形),则 G 必为黑(因为原为 RB-tree,必须遵循规则3,隐含父子节点不不得同时为红)。于是,根据 X 的插入位置及外围节点(S 和 GG)的颜色,有了以下四种情况:

情况1:S 为黑且 X 为外侧插入。我们先对 P,G 做一次单旋转,并更改 P,G 颜色,即可重新满足红黑树的规则 3。
在这里插入图片描述
情况2:S 为黑且 X 为内侧插入。我们必须先对 P,X 做一次单旋转,并更改 G,X 颜色,再将结果对 G 做一次单旋转,即可满足红黑树规则。如下图:

在这里插入图片描述
情况3:S 为红, X 为外侧插入且 GG 为黑。先对 P 和 G 做一次单旋转,并改变 X 的颜色。

在这里插入图片描述
情况4:S 为红, X 为外侧插入且 GG 为红。先执行情况 3 中的步骤,因为改变了颜色,GG 亦为红,还要持续网上做,直到不再有父子节点同时为红的情况。

在这里插入图片描述

3、由上而下的程序

为了避免情况 4 “父子节点皆为红色” 的情况持续向 RB-tree 的上层结构发展,形成处理时效上的瓶颈,我们可以施行一个由上而下的程序:此程序的目的是通过提前的修改,把情况 4 给规避掉。假设新增节点为 A,那么就延着 A 的路径,只要看到有某节点 X 的两个子节点皆为红色,就把 X 改为红色,并把两个子节点改为黑色。如下图所示:
在这里插入图片描述
改掉之后,如果 X 的父节点 P 亦是红色(注意,此时 S 绝不可能为红),就得像情况 1 一样做一次单旋转并改变颜色,或是像情况2 一样做一次双旋转并改变颜色。

在此之后,节点 35 的插入就很单纯了:要么直接插入,要么插入后在做一次单或者双旋转就可以了。

在这里插入图片描述

4、RB-tree 的节点设计

RB-tree 有红黑二色,并且拥有左右子节点。由于 RB-tree 的各种操作时常需要上溯其父节点,所以特别在数据结构中安排了一个 parent 指针。为了有更大的弹性,节点分为两层。如下所示:

typedef bool
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值