最近觉得C++生疏了,拿出侯捷的《STL源码剖析》翻了翻,看到C++ set,map底层实现机制,其中采用的就是红黑树数据结构,另外Linux内核对内存管理和进程调度都用到了红黑树,看来它不能让人小视。自己从网上和书上重新看了下红黑树,把个人的理解放到博客上,跟大家讨论,也作为自己的重新梳理的方式。
红黑树(Red-Black Tree)
它是在1972 年由Rudolf Bayer 发明的,他称之为"对称二叉B 树",它现代的名字是在Leo J. Guibas 和Robert Sedgewick 于1978 年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
红黑树本身是二叉搜索树,同时它应该始终满足五个性质:
红黑树每个节点颜色非红即黑;
根节点颜色必须为黑色;
每个叶节点(指的NULL指针节点)颜色均为黑;
不可以出现相邻的两个红色节点;
对于每个节点,其左右子树中的黑色节点个数必须相等;
一棵正常的红黑树如下图(引自wiki):

红黑树的难点在于插入和删除操作涉及到的红黑树重新调整问题,关于原理性问题,有篇文章《红黑树原理详解》,作者:余强. 讲的比较清楚,也可以参照《CLRS》第13章红黑树的描述,以下主要结合c语言实现代码加注释的方式进行分析,编完代码后进行了一定的测试,如果还存在问题,可回帖反馈,我会进行更改,谢谢。
插入操作:
新插入一个节点时,其颜色未定,可以选择黑色也可以选择红色,但是仔细看下上述红黑树5个性质,会发现,插入黑色节点必然会导致性质5被破坏(空树除外),而如果插入红色节点,则可能破坏性质4,这其中有一定的几率无需调整红黑树(父节点为黑色),因此插入的新节点颜色设置为红色,以下插入操作均不考虑是空树和父节点是黑色的情况,因为这两种情况无需进行调整。
而如果发生上面说的破坏性质4,即新插入节点与父节点均是红色的情况,则我们需要将这两个相邻红色节点分开,以使性质4重新被满足,而涉及到的调整则需要看新插入节点的父节点、叔父节点以及祖父节点颜色而定,可以分情况讨论之;
首先考虑叔父节点的颜色,这里以叔父节点的颜色来划分接下来的调整操作是因为插入的新节点与其父节点均为红色,目的为了将这两个红色节点分开,可以通过性质推理知祖父节点必然为黑色,因为插入新节点前,树是满足性质的,而父节点颜色为红色,因此祖父节点必然为黑色。调整颜色过程中,如果需要改变父节点颜色,则必然需要考虑叔父节点,因此叔父节点是插入操作分情况讨论的关键点。
在介绍插入后红黑树重新调整前,首先引入左旋操作和右旋操作,在红黑树所有调整中,均采用左右旋操作解决节点移动问题,左右旋操作并不破坏二叉搜索树的性质,因此不会引入额外的重新对红黑树进行排序的负担,具体左右旋操作可参考其他红黑树相关文章或下文中对于左右旋操作的代码分析加注释;
重回正题,首先对插入操作所需要的调整进行分情况讨论,再次强调父节点为黑色的情况不分析,因为无需作过多调整,所以下面操作中父节点颜色均为红色:
叔父节点颜色为黑色:


以上两种情况为插入节点的父节点在祖父节点的左子树情况,当位于右子树时,情况类似。
以上两种情况,即新插入节点分别为外侧插入和内侧插入时,需要将父节点和新节点的相邻红色分开,该两种情况下叔父节点应该为NULL节点(如果有不正确,请大家指正

)
因此调整操作是以祖父节点为基点,父节点和祖父节点的连接为轴进行右旋转(内侧插入即第二种情况必须先以父节点为基点进行左旋调整),然后改变父节点和祖父节点的颜色。

新节点外侧插入情况:以祖父节点为基点,右单选,改变父节点和祖父节点颜色;

新节点内侧插入情况:先对父节点左单选(如果这里不进行左旋转,则经过下一步的右旋转后,新节点即成为祖父节点的左孩子,如果祖父节点为红色,则会引入额外的调整和麻烦),改变新节点和祖父节点颜色,再对祖父节点右单旋;
叔父节点颜色为红色

该情况下比较简单,因为叔父和父节点都是红色,而且祖父节点为黑色,则将祖父节点颜色变为红色,父节点和叔父节点颜色为黑色,即可消除相邻的两个红色节点而且不改变相应的黑高度,此时如果曾祖父节点颜色为黑色,则调整结束,如果曾祖父节点颜色为红色,则可将祖父节点视为新节点,递归新插入情况,迭代向上处理。

总体来说插入情况相对比较简单,主要涉及上述几种操作,以下是c语言相关红黑树插入实现代码:
/*
* key:新插入节点键值,root:红黑树根节点
* 红黑树节点插入
* 1、插入新节点
* 2、旋转红黑树并做颜色调整
*/
rb_node_t *rb_tree_insert(int key, rb_node_t* root)
{
rb_node_t *last_node;
rb_node_t *curnode;
/* 创建节点 */
rb_node_t *node = (rb_node_t *)malloc(sizeof(rb_node_t));
node->key = key;
curnode = root; //temp node,just for save something
/* 树为空 */
if (NULL == root)
{
node->color = black;
node->left_child = NULL;
node->right_child = NULL;
node->parent = NULL;
return node;
}
/* 向下搜索,直到找到相应的位置可以插入 */
while (curnode)
{
last_node = curnode;
node->key > curnode->key ? (curnode = curnode->right_child) : (curnode = curnode->left_child);
}
/* 判断插入搜索到的节点的左孩子还是右孩子 */
if (node->key > last_node->key)
last_node->right_child = node;
else
last_node->left_child = node;
node->parent = last_node; //回马枪设置父节点
node->left_child = NULL;
node->right_child = NULL;
node->color = red;
/* 重新使红黑树调整为平衡状态 */
root = rb_tree_rebalance(node, root);
return root;
}
删除操作:
红黑树节点删除操作后的调整相比插入操作更加复杂,但是同样可以分情况讨论之。
首先红黑树删除同样采取跟二叉搜索树同样的删除方式,即如果需要删除节点A,则将A左子树中最大的节点(即最右边节点)和右子树中最小的节点(最左边的节点)删除,然后用删除节点替换A节点。
如下图:

需要删除8节点时,先搜索到7或9节点,将对应节点删除掉,同时将7或9的节点替换8的节点,详细参考请查阅二叉搜索树的删除。
相关推荐
下面将详细介绍红黑树的概念、性质以及如何在Java中实现它。 **1. 红黑树的概念** 红黑树是由Rudolf Bayer在1972年提出的,它是一种特殊的二叉查找树,每个节点都带有颜色属性,可以是红色或黑色。它的主要目标是在...
- 红黑树的查找操作与普通的二叉查找树类似,遵循“左小右大”的原则。由于红黑树保持了大致的平衡,查找效率接近于O(log n)。 5. **C++实现**: - 在C++中,红黑树的实现通常会定义一个包含颜色属性的节点结构体...
本文将详细介绍红黑树的基本概念、特性以及在实际操作中的应用,旨在为学习者提供一个完整的红黑树知识框架。 ### 红黑树的概念与特性 红黑树是一种自平衡的二叉查找树,旨在通过维护一系列性质来确保树的平衡性。...
通过上述内容的介绍,我们可以看到红黑树作为一种高效的自平衡二叉搜索树,在算法和数据结构的学习中占有极其重要的地位。它不仅在理论上具有很高的研究价值,在实际应用中也有着广泛的应用场景,如数据库索引、符号...
### 中科大红黑树插入算法实验报告 ...通过以上代码和分析,我们可以清晰地了解到红黑树如何在保证树的平衡性的同时,也能够有效地执行插入操作。这种数据结构的高效性和灵活性使其成为许多实际应用场景中的首选。
本篇通过分析给出的代码片段,详细介绍了红黑树的基本概念以及其实现细节。红黑树作为一种高效的数据结构,在实际应用中非常广泛,尤其是在需要频繁插入和删除操作的场景下。通过对红黑树的理解和实现,能够帮助...
(不需要资源分,不能修改上次的,只好重传了...红黑树算法(算法导论) 详解 【for_wind】,介绍了红黑树性质,详细分析了红黑树旋转,插入,删除等基本操作。其中算法的伪代码和算法导论中一致。 个人总结的,分享了。
通过以上对红黑树和区间树的详细介绍,我们可以看到这两种数据结构各有特点,适用于不同的应用场景。红黑树因其自平衡的特性,在需要频繁更新数据的同时保持高效的操作性能方面具有明显优势;而区间树则在处理区间...
#### 三、左倾红黑树介绍 文档提到的“左倾红黑树”(Left-Leaning Red-Black Trees, LLRB Trees)是红黑树的一种简化变体,旨在进一步降低代码的复杂度。具体来说,左倾红黑树将所有红色链接都保持向左倾斜,这种...
5. 平均情况分析:大多数算法教材中的红黑树分析集中在最坏情况下的性能,而塞德威克教授提出了对红黑树进行平均情况分析的可能性,这可以对算法的实际性能有更深入的理解。 6. 现代实现:红黑树在现代计算基础设施...
接下来,我们通过一个具体的Java类`RedBlackTree`来详细介绍红黑树的基本操作实现,包括插入和删除操作。 ```java class RedBlackTree { private static final boolean RED = true; private static final boolean...
文详细介绍了基于红黑树实现的 `Set` 和 `Map` 容器,包括其底层设计原理、插入和删除操作的实现细节、性能分析与优化策略,以及实际应用场景和未来发展方向。通过采用红黑树的数据结构,`Set` 和 `Map` 容器能够...
本项目“数据结构课程设计”是一个结合了Qt框架和红黑树算法实现的个人通讯录系统,旨在提升开发者对于数据结构的理解与应用能力,同时也展示了后端开发中界面交互的设计。 Qt是一个跨平台的C++图形用户界面应用...
下面详细介绍红黑树的相关知识点: 一、红黑树的定义和特性 红黑树是一种自平衡的二叉查找树,它满足以下几个特性: 1. 根节点和叶子节点都是黑色的。 2. 不能有连续两个红色的节点。 3. 从任一节点到它所能到达...
理解这些核心数据结构(如二叉树、二叉查找树和红黑树)及其相关算法对于软件开发人员至关重要,尤其是在设计高效的数据处理系统时。此外,掌握复杂度分析有助于我们在实际应用中做出更合理的决策,选择最适合当前...
- **Red-Black Trees**:重点介绍红黑树的性质、旋转操作、插入与删除算法。 - **Augmenting Data Structures**:讨论如何通过增强现有数据结构来解决更复杂的问题。 - **学习目标**:掌握各种数据结构的特性和...
根据给定的文件信息,我们可以深入探讨算法设计与分析这一主题,特别关注于红黑树这一复杂但高效的数据结构。 ### 算法设计与分析概览 “算法设计与分析”课程由徐云教授在2006年中国科学技术大学秋季学期授课,...
本资源摘要信息集中介绍了各种搜索树的原理和应用,包括二叉搜索树、AVL树、B-树、红黑树等。这些搜索树都是数据结构与算法的重要组成部分,广泛应用于数据库、文件系统、编译器等领域。 二叉搜索树 二叉搜索树是...
算法导论是计算机科学领域的经典教材之一,它系统地介绍了算法以及算法分析的基本理论和方法,适合于计算机专业的学生和从业者深入学习。 在描述中提到,文档内容是部分课后题的答案,并非全部,这意味着该文档是一...