【C++进阶】map

86 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第N天,点击查看活动详情

  1. 红黑树 🍃 1.1 红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路 径会比其他路径长出俩倍,因而是接近平衡的。

🍃 1.2 红黑树的性质 每个结点不是红色就是黑色 根节点是黑色的 如果一个节点是红色的,则它的两个孩子结点是黑色的 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点 每个叶子结点都是黑色的(此处的叶子结点指的是空结点) 思考:为什么满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点 个数的两倍?

答:假设黑色节点数量有N个,最短路径为:logN,最长路径为:2*logN,因此最长路径中节点个数不会超过最短路径中节点个数的两倍,所以如果用红黑树来完成查找效率也是非常高的。

🍃 1.3 红黑树节点的定义 //节点不是黑就是红,因此可以直接用枚举 e颜色给黑色,那么必然会破环性质4(每条路径上包含相同数目的黑节点),如果破坏性质4代价会非常大,这是一种全局的破坏,其他每条路径的节点会因该路径增加了一个黑节点而不满足红黑树性质,调整起来非常麻烦;那么如果我们默认颜色给红色呢,必然会破坏性质3(没有连续的红节点),但是破坏这条性质只会影响当前路径,并不会对其他路径造成影响,影响面小。所以综上所述我们不难发现,默认给成红色是更好的。

🍃 1.4 红黑树结构 在STL中,红黑树的实现中增加一个头结点,因为跟节点必须为黑色,为了与根节点进行区分,将头结点给成黑色,并且让头结点的 pParent 域指向红黑树的根节点,pLeft域指向红黑树中最小的节点,_pRight域指向红黑树中最大的节点,如下:

注意: 在下面的实现中,我们采用不带头节点的方式来模拟实现红黑树

🍃 1.5 红黑树的插入操作 红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此红黑树的插入可分为两步:

按照二叉搜索树规则插入新节点

检测新节点插入后,红黑树的性质是否造到破坏

因为新节点的默认颜色是红色,因此:如果其父节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的父节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:

在分情况讨论之前记住一句话:关键看叔叔的脸色!

情况一: cur为红,p为红,g为黑,u存在且为红

情况二: cur为红,p为红,g为黑,u不存在/u为黑

情况三: cur为红,p为红,g为黑,u不存在/u 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 🍃 1.7 红黑树与AVL树的比较 —