C++ 实现红黑树:深入理解 STL map 底层原理
红黑树概述
红黑树本质上是一棵二叉搜索树,每个节点额外增加了一个颜色位(红色或黑色)。通过对路径上颜色的约束,它确保了没有一条路径会比其他路径长出两倍,从而实现了近似平衡。
核心规则
- 颜色:每个节点非红即黑。
- 根节点:必须是黑色。
- 红色限制:若节点为红色,其子节点必须为黑色(无连续红节点)。
- 黑高一致:从任一节点到其所有叶子(NIL)的简单路径上,包含相同数量的黑色节点。
注:《算法导论》中提到的'叶子节点(NIL)都是黑色的'是为了方便理论推导。在实际代码实现中,通常不需要显式创建 NIL 节点,只需在逻辑上处理空指针即可。

为什么最长路径不超过最短路径的 2 倍?
根据规则 4,每条路径的黑色节点数量(黑高 bh)是固定的。极端情况下,最短路径全为黑色,长度为 bh。而根据规则 2 和 3,任意路径不能有连续红节点,因此最长路径是一黑一红交替,长度最多为 2 * bh。综合来看,树的高度 h 满足 bh <= h <= 2 * bh。
效率分析
假设节点数为 N,高度为 h,则有 2^h - 1 <= N <= 2^(2*h) - 1。由此可推导出 h ≈ logN。这意味着红黑树的增删查改操作在最坏情况下的时间复杂度仍为 O(logN)。
相比 AVL 树,红黑树对平衡的控制更宽松,插入时旋转次数更少,因此在频繁插入的场景下表现更优,这也是 STL 容器选择它作为底层结构的原因。

红黑树的实现细节
数据结构定义
我们需要一个节点结构体,包含键值对、左右子节点、父节点以及颜色属性。为了便于回溯调整,父指针必不可少。
enum Colour { RED, BLACK };
template<class K, class V>
struct RBTreeNode {
std::pair<K, V> _kv;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode( std::pair<K, V>& kv)
: _kv(kv), _left(), _right(), _parent(), _col(RED) {}
};
< , >
{
RBTreeNode<K, V> Node;
:
:
Node* _root = ;
};





