写在前面
红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
红黑树是在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。
红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的:它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
俺家司令买完东西后,我俩经常会发生这样的一段对话:
司令:你猜我买的这个多少钱? 我: 1000
司令: 高了 我: 500
司令: 低了: 我: 750
...... 直到最后猜中
这样说大家应该已经猜到了是「二分查找法」,通过这个例子我想要引出的是 树,来看图片
程序中的树其实是我们日常看到的树的倒影,或者发挥一下想象,倒影也可以是树根
红黑树
假设我们插入的新节点为 X
将新插入的节点标记为红色
如果 X 是根结点(root),则标记为黑色
如果 X 的 parent 不是黑色,同时 X 也不是 root:
3.1 如果 X 的 uncle (叔叔) 是红色
3.1.1 将 parent 和 uncle 标记为黑色
3.1.2 将 grand parent (祖父) 标记为红色
3.1.3 让 X 节点的颜色与 X 祖父的颜色相同,然后重复步骤 2、3
话不多说,看下图
跟着上面的公式走:
将新插入的 X 节点标记为红色
发现 X 的 parent (P) 同样为红色,这违反了红黑树的第三条规则「不能有两个连续相邻的红色节点」
发现 X 的 uncle (U) 同样为红色
将 P 和 U 标记为黑色
将 X 和 X 的 grand parent (G) 标记为相同的颜色,即红色,继续重复公式 2、3
发现 G 是根结点,标记为黑色
结束
当出现 uncle 是黑色的时候我们第一步要考虑的是 旋转 ,这里先请小伙伴不要关注红黑树的第 4 条规则,主要是为了演示如何旋转的,来一点点看,不要看图就慌,有解释的 :
情况如下
这种情况很简单,想象这是一根绳子,手提起 P 节点,然后变色即可
左右
左旋: 使 X 的父节点 P 被 X 取代,同时父节点 P 成为 X 的左孩子,然后再应用 左左情况
右右
与左左情况一样,想象成一根绳子
右左
右旋: 使 X 的父节点 P 被 X 取代,同时父节点 P 成为 X 的右孩子,然后再应用 右右情况
你说的动图在哪里,你个大骗子,别着急,现在就为小伙伴们奉上动图演示,来说明公式的使用:
案例一
插入 10,20,30,15 到一个空树中
向空树中第一次插入数字 10,肯定是 root 节点
root 节点标记成黑色
向树中插入新节点 20,标记为红色
20 > 10,并发现 10 没有叶子节点,将新节点 20 作为 10 的右孩子
向树中插入新节点 30,标记为红色
30 > 10,查找 10 的右子树,找到 20
30 > 20,继续查找 20 的右子树,发现 20 没有叶子节点,将值插在此处
30 和 20 节点都为红色,30 为右孩子,20 也为右孩子,触发了 右右情况
通过一次旋转,提起 20 节点
20 节点是根结点,标记为黑色
向树中插入新节点 15,标记为红色
通过比对大小和判断是否有叶子节点,最终插值为 10 节点的右孩子
15 和 10 节点都为红色,15 的 uncle 节点 30 也为红色
按照公式,将 15 的 parent 10 和 uncle 30 更改为黑色
让 15 节点 grand parent 20 的颜色与 15 节点的颜色一样,变为红色
20 为根结点,将其改为黑色
继续插入其他节点只不过反复应用上面的公式,上面应用到的红黑树工具,可以暂停动画效果,一帧一帧的看红黑树的转换过程,这样通过练习,查看公式,观察变化三管齐下,红黑树的入门理解应该完全不再是问题了