C++ 红黑树深度解析
红黑树(Red-Black Tree)本质上是一棵二叉搜索树,但在每个节点上增加了一个存储位表示颜色(红色或黑色)。通过对路径上颜色的约束,它确保了没有一条路径会比其他路径长出两倍,从而实现了近似平衡。这意味着红黑树的插入、删除和查找操作在最坏情况下也能保持 O(log n) 的时间复杂度。
相比 AVL 树,红黑树对平衡性的控制没那么严格,因此在插入相同数量的节点时,红黑树的旋转次数更少,工程实践中更为常用。
1. 红黑树的核心规则
要理解红黑树,首先得掌握它的五条性质(通常归纳为四条主要规则加 NIL 隐含规则):
- 节点颜色:每个节点要么是红色,要么是黑色。
- 根节点:根节点必须是黑色。
- 红色节点限制:如果一个节点是红色,则它的两个子节点都必须是黑色(即不能有两个连续的红色节点)。
- 黑色高度一致:从任一节点到其每个叶子(NIL)的所有路径上,包含相同数目的黑色节点。
- NIL 节点:所有的叶子节点(NIL)都是黑色的。
关于 NIL 节点的说明:在《算法导论》等书籍中,NIL 被视为外部节点,代表空指针。它们的存在是为了方便准确标识所有路径的黑色节点数量。实际代码实现中,我们通常用
nullptr来代替显式的 NIL 节点。
为什么最长路径不超过最短路径的 2 倍?
假设最短路径全是黑色节点,长度为 bh(黑色高度)。根据规则 3,任意路径不会有连续的红节点,所以极端情况下最长路径是一黑一红交替组成,长度约为 2 * bh。因此,理论上的高度 h 满足:bh <= h <= 2 * bh。这使得红黑树的高度始终保持在 O(log n) 级别。
2. 红黑树的结构实现
我们用枚举值来表示颜色,并在节点结构体中增加父指针以便向上回溯调整。
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
// 枚举值表示颜色,保障不是黑色就是红色
enum Color {
BLACK,
RED
};
// 红黑树节点模板
template<class K, class V>
struct RBTreeNode {
pair<K, V> _kv;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Color _col;
// 初始化构造函数
RBTreeNode(const pair<K, V>& kv)
:_kv(kv), _left(nullptr), _right(), _parent(), _col(RED) {}
};


