大名鼎鼎的红黑树,究竟是何方神圣?
在学习 C++ STL 的时候,我们总会碰到这样一件事:
map
、set
这些容器,查找、插入、删除的复杂度都是 O(log n) ,而且还能保持有序。
这背后的"功臣",就是 红黑树(Red-Black Tree) 。
那么问题来了:红黑树究竟是个啥?为什么它能这么高效?今天我们就好好拆解一下。
1. 红黑树是啥?
红黑树是一种 自平衡二叉搜索树 。
换句话说,它就是一种二叉搜索树(BST),但在插入或删除时,会自动做一些"旋转、变色"的操作,来保证树的高度不会退化。
为什么要搞"平衡"?
- 普通 BST 最坏情况下可能退化成链表,查找复杂度变成 O(n) 。
- 红黑树通过约束节点颜色和形态,保证树的高度始终在 O(log n) 。
所以,它是介于"性能"和"实现复杂度"之间的一个折中方案。
2. 红黑树的 5 条性质
红黑树之所以能保持平衡,靠的是一套规则:
- 每个节点要么是红色,要么是黑色。
- 根节点永远是黑色。
- 所有叶子节点(NIL 空节点)都是黑色。
- 如果一个节点是红色,它的子节点必须是黑色(不能连续两个红节点)。
- 从任意节点到其所有叶子的路径上,黑色节点数相同(黑高一致)。
这些规则确保了:
- 不会出现长链条(黑节点高度平衡)。
- 红节点插入后能通过变色/旋转修复树形。
最终,红黑树的高度最多是 2 * log2(n+1)
,保证查找、插入、删除都是 O(log n) 。
3. 红黑树的"变色与旋转"
当我们往树里插入一个新节点时,可能会破坏红黑树的平衡。
修复的方式主要有两种:
- 变色:把某些红节点变黑,或者反过来。
- 旋转:通过左旋或右旋调整树的形态,让它重新平衡。
比如,当一个红节点插到红节点下面,就违反了"不能连续两个红"的规则,这时可能就需要"叔叔变色"或者"父亲旋转"。
很多教材在这里会配图展示插入时的各种情况(父红叔黑 / 父红叔红等),这就是红黑树实现里最复杂的部分。

4. 红黑树的应用
红黑树之所以"大名鼎鼎",在前面也可以看出来了,它很实用。
在很多编程语言的标准库中,它都是底层支柱:
- C++ STL :
map
、set
、multimap
、multiset
- Java :
TreeMap
、TreeSet
- Linux 内核:进程调度、内存管理(虚拟内存区域 VMA 组织)
- 数据库/编译器:符号表、索引结构
凡是需要 有序、可快速查找/插入/删除 的场景,红黑树都是首选。
5. 为什么不是别的树?
有人可能会问:这不是还有 AVL 树、Splay 树等一众好树嘛,为什么就只有红黑树如此受欢迎?我们来稍稍对比以下就知道了。
- AVL 树:更严格的平衡 → 查找快,但旋转多,插入删除开销大。
- Splay 树:更适合"局部性"访问 → 热点数据快,但最坏情况可能很慢。
- 红黑树 :平衡性没 AVL 那么极端,但旋转次数少 → 综合性能更优。
这也是为什么 C++ STL、Java 都选了红黑树作为底层实现。
6. 小结
- 红黑树就是棵 自平衡二叉搜索树,核心是用颜色来判断是否平衡,然后用旋转来保持平衡。
- 它的目标:保证操作在 O(log n) ,避免 BST 退化。
- 应用广泛:STL 容器、Java 集合、操作系统、数据库等。
- 和 AVL 树相比,红黑树牺牲了查找的极致性能,换来更高效的插入与删除。
所以说,红黑树并不是"最平衡"的树,但却是工程上最实用的平衡树之一。