红黑树 数据结构描述
c++map的底层实现原理

c++map的底层实现原理
C++ STL中的map是通过红黑树实现的,红黑树是一种自平衡的二叉查找树,它的插入、删除、查找操作都能在对数时间复杂度内完成,可以保证较稳定的性能。
具体来说,map内部是用一颗红黑树(Red-Black Tree)实现的。
红黑树是一种对平衡性要求比较低的二叉查找树(Binary Search Tree),在红黑树上进行查找、插入、删除等操作的时间复杂度都是log(N)。
红黑树的特点是每个节点要么是红色,要么是黑色,并且满足以下规则:
1、根节点是黑色的;
2、每个叶子节点都是黑色的空节点(NIL节点);
3、如果一个节点是红色的,则它的子节点必须是黑色的;
4、从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点;
由于map底层采用红黑树实现,因此它具有以下特点:
1、自动排序;
2、查找、插入、删除操作的时间复杂度都是O(logN),极端情况下会退化成链表;
3、可以支持迭代器操作,比如反向迭代;
4、支持按照自定义规则排序;
综上所述,map的底层实现原理是通过红黑树实现的,红黑树是一种自平衡的二叉查找树,能够保证较稳定的性能。
Linux与minix调度机制比较

Minix3和linux3调度机制比较摘要minix3和linux是两个非常不同的系统,本文将对两个系统的调度机制进行比较。
minix3采用的是多级的进程队列进行调度。
为了防止系统出现挂起的情况,采用动态优先级的方法。
随后,文章将介绍minix3的调度算法中的一些具体实现;由于linux2.6中实现了多种的调度算法,本文选择了最常用的CFS(完全公平算法)来做介绍。
最后,文章对两类算法的应用做了对比和总结。
关键字:minix3,linux,进程调度,CFS1.Minix3的调度算法1.1基本思想一个多级的排队系统。
有16个排队队列,但实际上可以编译定义更多或更少的队列。
系统刚运行的时候一般不会使用这么多的队列,而仅使用其中几个。
进程的优先级基本上由其所在队列的优先级所决定。
选择进程运行的时候,调度器将从最高优先级队列中的进程开始选,如果有,则选取队首进程运行;若没有,则到下一个次优先级的队列中去选进程去执行。
1.2 CPU时间分配和防止系统挂起(hang)进程调度中既要给与高优先级进程更多的机会去运行,但同时也要防止系统老是被一个高优先级的进程所占用,出现低优先级进程的“进程饥饿”,最后甚至造成系统挂起的问题。
Minix3采用以下的方法。
首先,队列内采取时间片轮转的方法。
每个进程都有一个时间片,每次时间片用完,调度器都要进行进程调度。
优先级高的进程一般有较大的时间片。
对于某个优先级队列中的进程而言,一个进程运行完它的时间片后就会被放到原先优先级队列的尾部并分配一个新的时间片,使得队列中的进程能轮转地公平的得到运行的机会。
其次,对于队列间,采取如下动态优先级的策略。
但如果队列中只有一个进程,那这个进程在时间片运行完后,仍会立即继续下一个时间片地运行。
为了防止这种情况,但一个进程连续两个时间片地运行完后,将被放在一个较低的运行队列中。
而当进程没有妨碍其他进程的运行(即其时间片用完后,调度器调度了其他的进程运行)时,它的优先级又会不断提高直到到它能回到的(所允许的)最大优先级。
算法导论-9.红黑树习题

算法导论-9.红⿊树习题这⼀篇解决《算法导论》中红⿊树章节的部分习题,在上⼀篇⾃⼰亲⾃实现红⿊树后,解决这些题⽬就轻松多了。
练习13.1-6 在⼀棵⿊⾼度为 $k$ 的红⿊树中,内节点最多有多少个?最少有多少个?⿊⾼度为 $k$ 的⼆叉树,全⾼度最⼩为 $k+1$,最⼤为 $2k+2$ 。
内节点最多有 $2^{k+1}-1$ 个,这种情况下红⿊树中没有红节点,⿊节点全满(满⾜所有叶⼦节点⿊⾼度⼀致的条件);内节点最多有 $2^{2k+2}-1=4^{k+1}-1$ 个。
这种情况下红⿊树全满。
练习13.1-7 在 $n$ 个关键字上构造出来的⼆叉树,红节点与⿊节点个数的⽐值最⼤为多少?最⼩是多少?红节点最多时,⽐值为:$$\frac{n-2^{h-1}-2^{h-3}-...-(2)-1}{2^{h-1}+2^{h-3}+...+(2)+1},h=\lfloor\lg n\rfloor$$红节点最少时,⽐值时为:$$\frac{n-2^{\lfloor\lg n\rfloor}}{2^{\lfloor\lg n\rfloor}}$$练习13.2-2 证明,在⼀棵 $n$ 个节点的⼆叉查找树中,刚好有 $n-1$ 种可能的旋转。
思路:每⼀个可能的旋转对应于⼀条边,每⼀个条边也只能对应⼀个可能的旋转,因此可能的旋转数就是边的数⽬。
每⼀条边都对应⼀个⼉⼦节点,每⼀个节点(除了根节点)都对应⼀个边,所以边的数⽬为 $n-1$ ,也就是可能的旋转的数⽬。
练习13.2-4 证明任意⼀颗含有 $n$ 个节点的⼆叉查找树都能通过 $O(n)$ 次旋转,转变为另⼀颗含有同样节点(节点位置可以任意不⼀样,但仍然保持⼆叉查找树性质)的⼆叉查找树。
思路:考虑⼀颗⼆叉查找树的“右链”,即从根节点向具有最⼤节点值的节点的路径。
不断地右旋右链上具有左⼦树的节点,每⼀次旋转可以使右链上多⼀个节点,(⼜,右链上⾄少有⼀个节点,根节点),所以⾄多 $n-1$ 次右旋后,⼆叉树的右链上连接了所有的节点,这时⼆叉树实际上称了⼀个已排序(旋转保持⼆叉查找树的性质)的单链表。
算法工程师面试真题单选题100道及答案解析

算法工程师面试真题单选题100道及答案解析1. 以下哪种数据结构适合用于实现快速查找最大值和最小值?A. 栈B. 队列C. 堆D. 链表答案:C解析:堆可以快速地获取最大值和最小值。
2. 快速排序在最坏情况下的时间复杂度是?A. O(nlogn)B. O(n^2)C. O(n)D. O(logn)答案:B解析:快速排序在最坏情况下,每次划分都极不均匀,时间复杂度为O(n^2)。
3. 以下哪种算法常用于在未排序的数组中查找特定元素?A. 冒泡排序B. 二分查找C. 顺序查找D. 插入排序答案:C解析:顺序查找适用于未排序的数组查找特定元素。
4. 一个有向图的邻接表存储结构中,顶点的邻接点是按照什么顺序存储的?A. 随机顺序B. 顶点编号的大小顺序C. 插入的先后顺序D. 无法确定答案:C解析:邻接表中顶点的邻接点是按照插入的先后顺序存储的。
5. 深度优先搜索遍历图的时间复杂度是?A. O(n)B. O(n + e)C. O(n^2)D. O(e)答案:B解析:深度优先搜索遍历图的时间复杂度为O(n + e),其中n 是顶点数,e 是边数。
6. 以下哪种排序算法是稳定的排序算法?A. 快速排序B. 希尔排序C. 冒泡排序D. 选择排序答案:C解析:冒泡排序是稳定的排序算法。
7. 一个具有n 个顶点的无向完全图,其边的数量为?A. n(n - 1) / 2B. n(n - 1)C. n^2D. 2n答案:A解析:无向完全图的边数为n(n - 1) / 2 。
8. 动态规划算法的基本思想是?A. 分治法B. 贪心算法C. 把问题分解成多个子问题并保存子问题的解D. 回溯法答案:C解析:动态规划的基本思想是把问题分解成多个子问题并保存子问题的解,避免重复计算。
9. 以下关于哈希表的说法,错误的是?A. 哈希表的查找时间复杂度为O(1)B. 哈希冲突可以通过开放定址法解决C. 哈希表的空间复杂度是固定的D. 哈希函数的设计会影响哈希表的性能答案:C解析:哈希表的空间复杂度不是固定的,取决于元素数量和负载因子等。
红黑树的应用场景

红黑树的应用场景
x
红黑树的应用场景
红黑树(Red-Black tree)是一种自平衡二叉搜索树,也叫蓝黑树,它是在计算机科学中用来维护有序的元素集合的一种数据结构。
它的特点是,任何一个节点的左右子树的高度只相差1——也就是说,它们自动调整自己,当插入或删除节点时,保持其平衡。
红黑树有多种应用场景。
其中最重要的就是在并发编程中使用它来保持同步性和正确性。
它可以用作字典、键值存储、排序等数据结构,可以用来解决缓存管理、查找最近的匹配项、查找最近的空位等问题。
此外,红黑树还广泛应用于操作系统、数据库系统等中。
红黑树在操作系统中的应用包括:操作系统特定的定时器任务队列的管理、连接状态表的管理(网络状态的保持)、文件系统中的元素索引、内存分页表的管理等。
红黑树也广泛应用于数据库系统,用作B+树、事务日志索引(控制数据库的性能)等,它们能够提供快速的查询、插入操作。
此外,红黑树在图形处理系统和CAD(Computer Aided Design,计算机辅助设计)程序中用于提供三维空间/曲面的模型数据结构设计。
它们也可以用作编译器的符号表,用于检查程序的语法和语义正确性。
总而言之,红黑树由于其自平衡的特性,被广泛用于不同的软
件领域中,解决涉及搜索、排序、索引和存储等问题。
红黑树的定义和节点结构

红黑树的定义和节点结构红黑树(Red-Black Tree)是一种自平衡的二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是红色或黑色。
红黑树具有如下性质:1. 每个节点要么是红色,要么是黑色。
2. 根节点是黑色。
3. 每个叶子节点(NIL节点,空节点)是黑色。
4. 如果一个节点是红色的,则它的两个子节点都是黑色的。
5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
红黑树的节点结构通常包含以下几个字段:1. 键值(Key):存储节点的关键字,用于进行搜索和比较。
2. 数据(Value):存储节点关联的数据。
3. 左子节点(Left):指向该节点的左子节点。
4. 右子节点(Right):指向该节点的右子节点。
5. 父节点(Parent):指向该节点的父节点。
6. 颜色(Color):表示节点的颜色,通常用布尔值或枚举类型表示。
红黑树的定义和节点结构相互依赖,通过节点间的关系和颜色属性,实现了树的自平衡。
下面将详细介绍红黑树的定义和节点结构。
红黑树的定义是基于二叉搜索树的基础上进行的。
二叉搜索树是一种有序的二叉树,对于任意节点,其左子节点的键值小于该节点的键值,而右子节点的键值大于该节点的键值。
这个性质使得在二叉搜索树上进行搜索、插入和删除等操作非常高效。
然而,如果只使用二叉搜索树,可能会出现树的不平衡情况,导致某些操作的时间复杂度变高。
为了解决这个问题,红黑树引入了节点的颜色属性,并通过一些特定的规则来保持树的平衡。
红黑树的节点结构包含了键值、数据和指向子节点的指针。
其中,键值用于进行搜索和比较,数据存储了节点关联的信息。
左子节点和右子节点分别指向该节点的左右子树,父节点指向该节点的父节点。
通过这些指针,可以在树中进行节点的插入、删除和查找等操作。
红黑树的节点还包含了颜色属性,用于表示节点的颜色。
颜色通常用布尔值或枚举类型表示,红色用true或RED表示,黑色用false 或BLACK表示。
C++容器详解

C++容器详解什么是容器⾸先,我们必须理解⼀下什么是容器,在C++ 中容器被定义为:在数据存储上,有⼀种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器。
很简单,容器就是保存其它对象的对象,当然这是⼀个朴素的理解,这种“对象”还包含了⼀系列处理“其它对象”的⽅法,因为这些⽅法在程序的设计上会经常被⽤到,所以容器也体现了⼀个好处,就是“容器类是⼀种对特定代码重⽤问题的良好的解决⽅案”。
容器还有另⼀个特点是容器可以⾃⾏扩展。
在解决问题时我们常常不知道我们需要存储多少个对象,也就是说我们不知道应该创建多⼤的内存空间来保存我们的对象。
显然,数组在这⼀⽅⾯也⼒不从⼼。
容器的优势就在这⾥,它不需要你预先告诉它你要存储多少对象,只要你创建⼀个容器对象,并合理的调⽤它所提供的⽅法,所有的处理细节将由容器来⾃⾝完成。
它可以为你申请内存或释放内存,并且⽤最优的算法来执⾏您的命令。
容器是随着⾯向对象语⾔的诞⽣⽽提出的,容器类在⾯向对象语⾔中特别重要,甚⾄它被认为是早期⾯向对象语⾔的基础。
在现在⼏乎所有的⾯向对象的语⾔中也都伴随着⼀个容器集,在C++ 中,就是标准模板库(STL )。
和其它语⾔不⼀样,C++ 中处理容器是采⽤基于模板的⽅式。
标准C++ 库中的容器提供了多种数据结构,这些数据结构可以与标准算法⼀起很好的⼯作,这为我们的软件开发提供了良好的⽀持!通⽤容器的分类STL 对定义的通⽤容器分三类:顺序性容器、关联式容器和容器适配器。
顺序性容器是⼀种各元素之间有顺序关系的线性表,是⼀种线性结构的可序群集。
顺序性容器中的每个元素均有固定的位置,除⾮⽤删除或插⼊的操作改变这个位置。
这个位置和元素本⾝⽆关,⽽和操作的时间和地点有关,顺序性容器不会根据元素的特点排序⽽是直接保存了元素操作时的逻辑顺序。
⽐如我们⼀次性对⼀个顺序性容器追加三个元素,这三个元素在容器中的相对位置和追加时的逻辑次序是⼀致的。
面试题——轻松搞定面试中的红黑树问题

⾯试题——轻松搞定⾯试中的红⿊树问题版权所有,转载请注明出处,谢谢!连续两次⾯试都问到了红⿊树,关键两次都没有答好,这次就完整地来学习整理⼀下。
没有学习过红⿊树的同学请参考:<<Introduction to Algorithms>> Chapter 13 Red-Black Trees Chapter 14 Augmenting Data Structures1.stl中的set底层⽤的什么数据结构?2.红⿊树的数据结构怎么定义的?3.红⿊树有哪些性质?4.红⿊树的各种操作的时间复杂度是多少?5.红⿊树相⽐于BST和AVL树有什么优点?6.红⿊树相对于哈希表,在选择使⽤的时候有什么依据?7.如何扩展红⿊树来获得⽐某个结点⼩的元素有多少个?8.扩展数据结构有什么步骤?9 为什么⼀般hashtable的桶数会取⼀个素数详细解答1.stl中的set底层⽤的什么数据结构?红⿊树2.红⿊树的数据结构怎么定义?[cpp]1. enum Color2. {3. RED = 0,4. BLACK = 15. };6.7. struct RBTreeNode8. {9. struct RBTreeNode*left, *right, *parent;10. int key;11. int data;12. Color color;13. };3.红⿊树有哪些性质?⼀般的,红⿊树,满⾜以下性质,即只有满⾜以下全部性质的树,我们才称之为红⿊树:1)每个结点要么是红的,要么是⿊的。
2)根结点是⿊的。
3)每个叶结点(叶结点即指树尾端NIL指针或NULL结点)是⿊的。
4)如果⼀个结点是红的,那么它的俩个⼉⼦都是⿊的。
5)对于任⼀结点⽽⾔,其到叶结点树尾端NIL指针的每⼀条路径都包含相同数⽬的⿊结点。
4.红⿊树的各种操作的时间复杂度是多少?能保证在最坏情况下,基本的动态⼏何操作的时间均为O(lgn)5.红⿊树相⽐于BST和AVL树有什么优点?红⿊树是牺牲了严格的⾼度平衡的优越条件为代价,它只要求部分地达到平衡要求,降低了对旋转的要求,从⽽提⾼了性能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
红黑树数据结构描述红黑树数据结构描述红黑树红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
它是在1972年由鲁道夫·贝尔发明的,他称之为"对称二叉B树",它现代的名字是在Leo J.Guibas和Robert Sedgewick于1978年写的一篇论文中获得的。
它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。
用途和好处红黑树和AVL树一样都对插入时间、删除时间和查找时间提供了最好可能的最坏情况担保。
这不只是使它们在时间敏感的应用如实时应用(real time application)中有价值,而且使它们有在提供最坏情况担保的其他数据结构中作为建造板块的价值;例如,在计算几何中使用的很多数据结构都可以基于红黑树。
红黑树在函数式编程中也特别有用,在这里它们是最常用的持久数据结构之一,它们用来构造关联数组和集合,在突变之后它们能保持为以前的版本。
除了O(log n)的时间之外,红黑树的持久版本对每次插入或删除需要O(log n)红黑树是的一种等同。
换句话说,对于每个2-3-4树,都存在至少一个数据元素是同样次序的红黑树。
在2-3-4树上的插入和删除操作也等同于在红黑树中颜色翻转和旋转。
这使得2-3-4树成为理解红黑树背后的逻辑的重要工具,这也是很多介绍算法的教科书在红黑树之前介绍2-3-4树的原因,尽管2-3-4树在实践中不经常使用。
性质红黑树是每个节点都带有颜色属性的,颜色或红色或黑色。
在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求性质1.节点是红色或黑色。
性质2.根是黑色。
性质3.所有叶子都是黑色(叶子是NIL节点)。
性质4.每个红色节点的两个子节点都是黑色。
从每个叶子到根的所有路径上不能有两个连续的红色节点性质5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
这些约束强制了红黑树的关键性质从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。
结果是这个树大致上是平衡的。
因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的。
要知道为什么这些特性确保了这个结果,注意到属性4导致了路径不能有两个毗连的红色节点就足够了。
最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。
因为根据属性5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。
在很多树数据结构的表示中,一个节点有可能只有一个子节点,而叶子节点包含数据。
用这种范例表示红黑树是可能的,但是这会改变一些属性并使算法复杂。
为此,本文中我们使用"nil叶子"或"空(null)叶子",如上图所示,它不包含数据而只充当树在此结束的指示。
这些节点在绘图中经常被省略,导致了这些树好像同上述原则相矛盾,而实际上不是这样。
与此有关的结论是所有节点都有两个子节点,尽管其中的一个或两个可能是空叶子。
操作因为每一个红黑树也是一个特化的二叉查找树,因此红黑树上的只读操作与普通二叉查找树上的只读操作相同。
然而,在红黑树上进行插入操作和删除操作会导致不再符合红黑树的性质。
恢复红黑树的属性需要少量(O(log n))的颜色变更实际是非常快速的和不超过三次树旋转对于插入操作是两次。
虽然插入和删除很复杂,但操作时间仍可以保持为O(log n)次。
插入我们首先以二叉查找树的方法增加节点并标记它为红色。
(如果设为黑色,就会导致根到叶子的路径上有一条路上,多一个额外的黑节点,这个是很难调整的。
但是设为红色节点后,可能会导致出现两个连续红色节点的冲突,那么可以通过颜色调换(color flips)和树旋转来调整。
)下面要进行什么操作取决于其他临近节点的颜色。
同人类的家族树中一样,我们将使用术语叔父节点来指一个节点的父节点的兄弟节点。
注意性质和性质总是保持着。
性质只在增加红色节点、重绘黑色节点为红色,或做旋转时受到威胁。
性质只在增加黑色节点、重绘红色节点为黑色,或做旋转时受到威胁。
在下面的示意图中,将要插入的节点标为N,N的父节点标为P,N的祖父节点标为G,N的叔父节点标为U。
在图中展示的任何颜色要么是由它所处情形所作的假定,要么是这些假定所暗含(imply)的。
对于每一种情况,我们将使用示例代码来展示。
通过下列函数,可以找到一个节点的叔父和祖父节点node grandparentnode n{return nparentparent;}node unclenode n{if nparent==grandparentnleftreturn grandparentnright;elsereturn grandparentnleft;}情形1新节点N位于树的根上,没有父节点。
在这种情形下,我们把它重绘为黑色以满足性质。
因为它在每个路径上对黑节点数目增加一,性质符合。
void insert_case1node n{if nparent==NULLncolor=BLACK;elseinsert_case2n;}情形2新节点的父节点P是黑色,所以性质没有失效(新节点是红色的)。
在这种情形下,树仍是有效的。
性质受到威胁,因为新节点N有两个黑色叶子儿子;但是由于新节点N是红色,通过它的每个子节点的路径就都有同通过它所取代的黑色的叶子的路径同样数目的黑色节点,所以这个性质依然满足。
void insert_case2node n{if nparentcolor==BLACKreturn;/*树仍旧有效*/elseinsert_case3n;}在下列情形下我们假定新节点有祖父节点,因为父节点是红色;并且如果它是根,它就应当是黑色。
所以新节点总有一个叔父节点,尽管在情形4和5下它可能是叶子。
情形3如果父节点P和叔父节点U二者都是红色,此时新插入节点N做为P的左子节点或右子节点都属于情形3,这里右图仅显示N做为P左子的情形则我们可以将它们两个重绘为黑色并重绘祖父节点G为红色用来保持性质。
现在我们的新节点N有了一个黑色的父节点P。
因为通过父节点P或叔父节点U的任何路径都必定通过祖父节点G,在这些路径上的黑节点数目没有改变。
但是,红色的祖父节点G的父节点也有可能是红色的,这就违反了性质。
为了解决这个问题,我们在祖父节点G上递归地进行情形1的整个过程。
(把G当成是新加入的节点进行各种情况的检查)void insert_case3node n{if unclen!=NULL&&unclencolor==RED{nparentcolor=BLACK;unclencolor=BLACK;grandparentncolor=RED;insert_case1grandparentn;}elseinsert_case4n;}在余下的情形下,我们假定父节点P是其父亲G的左子节点。
如果它是右子节点,情形4和情形5中的左和右应当对调。
情形4父节点P是红色而叔父节点U是黑色或缺少;还有,新节点N是其父节点P的右子节点,而父节点P又是其父节点的左子节点。
在这种情形下,我们进行一次调换新节点和其父节点的角色;接着,我们按情形5处理以前的父节点P。
这导致某些路径通过它们以前不通过的新节点N或父节点P中的一个,但是这两个节点都是红色的,所以性质没有失效。
void insert_case4node n{ifn==nparentright&&nparent==grandparentnleft{rotate_leftnparent;n=nleft;}else ifn==nparentleft&&nparent==grandparentnright{rotate_rightnparent;n=nright;}insert_case5n;}情形5父节点P是红色而叔父节点U是黑色或缺少,新节点N是其父节点的左子节点,而父节点P又是其父节点G的左子节点。
在这种情形下,我们进行针对祖父节点G的一次在旋转产生的树中,以前的父节点P现在是新节点N和以前的祖父节点G的父节点。
我们知道以前的祖父节点G是黑色,否则父节点P就不可能是红色如果P和G都是红色就违反了性质4,所以G必须是黑色。
我们切换以前的父节点P和祖父节点G的颜色,结果的树满足性质。
性质也仍然保持满足,因为通过这三个节点中任何一个的所有路径以前都通过祖父节点G,现在它们都通过以前的父节点P。
在各自的情形下,这都是三个节点中唯一的黑色节点。
void insert_case5node n{nparentcolor=BLACK;grandparentncolor=RED;ifn==nparentleft&&nparent==grandparentnleft{rotate_rightgrandparentn;} else{/*Here,n==n-parent-right&&n-parent==grandparent(n)-right*/rotate_leftgrandparentn;}}注意插入实际上是,因为上述所有调用都使用了。
删除如果需要删除的节点有两个儿子,那么问题可以被转化成删除另一个只有一个儿子的节点的问题(为了表述方便,这里所指的儿子,为非叶子节点的儿子)。
对于二叉查找树,在删除带有两个非叶子儿子的节点的时候,我们找到要么在它的左子树中的最大元素、要么在它的右子树中的最小元素,并把它的值转移到要删除的节点中如在所展示的那样。
我们接着删除我们从中复制出值的那个节点,它必定有少于两个非叶子的儿子。
因为只是复制了一个值而不违反任何属性,这就把问题简化为如何删除最多有一个儿子的节点的问题。
它不关心这个节点是最初要删除的节点还是我们从中复制出值的那个节点。
在本文余下的部分中,我们只需要讨论删除只有一个儿子的节点如果它两个儿子都为空,即均为叶子,我们任意将其中一个看作它的儿子。
如果我们删除一个红色节点,它的父亲和儿子一定是黑色的。
所以我们可以简单的用它的黑色儿子替换它,并不会破坏属性3和4。
通过被删除节点的所有路径只是少了一个红色节点,这样可以继续保证属性5。
另一种简单情况是在被删除节点是黑色而它的儿子是红色的时候。
如果只是去除这个黑色节点,用它的红色儿子顶替上来的话,会破坏属性5,但是如果我们重绘它的儿子为黑色,则曾经通过它的所有路径将通过它的黑色儿子,这样可以继续保持属性5。
需要进一步讨论的是在要删除的节点和它的儿子二者都是黑色的时候,这是一种复杂的情况。