C++ 伸展树与红黑树原理及实现详解
在平衡二叉搜索树(BBST)的家族中,伸展树和红黑树是两种极具代表性的结构。它们各有侧重:伸展树利用局部性原理,通过自调整优化频繁访问的场景;红黑树则通过颜色约束保证最坏情况下的性能稳定,是 STL std::map 等容器的底层基石。
1. 伸展树介绍
伸展树(Splay Tree)是一种自调整数据结构,由 John Edward Hopcroft 和 Robert Endre Tarjan 于 1985 年提出。与 AVL 树追求严格的高度平衡不同,伸展树不要求每次操作都保持完美平衡,而是将最近访问的节点通过旋转移动到根节点附近。
核心思想
- 单一旋转:将经常访问的节点上移。
- 移动到根部:假设节点会被再次访问,将其反复旋转至根位置。
每当执行搜索、插入或删除时,都会触发一次'伸展'(Splaying)操作,将目标节点移至根。这组规则包括三种旋转类型:
- 单旋转 (Zig):当父节点为根时执行。
- 一字形旋转 (Zig-Zig):当前节点与其父、祖父同侧时执行双旋。
- 之字形旋转 (Zig-Zag):当前节点与其父、祖父异侧时执行双旋。
这种策略使得频繁访问的节点始终靠近根部,虽然单次操作可能耗时 O(n),但在 m >= n 次操作的序列中,均摊时间复杂度为 O(log n)。
// 伸展算法伪代码逻辑
void splaying(Node* g, Node* p, Node* s) {
// g 是 p 的父结点,p 是 s 的父结点。算法将 s 移到根结点位置
while (s != root) {
if (s->parent == root) {
// 情况 1: 单旋转
rotate(s);
} else if (isSameSide(s, p, g)) {
// 情况 2: 一字形双旋转
rotate(p); rotate(g);
} else {
// 情况 3: 之字形双旋转
rotate(s); rotate(g);
}
}
}
2. 红黑树介绍
红黑树是一棵二叉搜索树,每个节点增加一个存储位表示颜色(红或黑)。通过对路径颜色的约束,确保没有一条路径比其他路径长出两倍。
2.1 红黑树的性质
- 根结点和所有外部结点(NIL)的颜色是黑色。
- 从根结点到外部结点的途中没有连续两个红色结点。
- 所有从根到外部结点的路径上都有相同数目的黑色结点(黑高度)。
2.2 效率分析
设根结点的黑高度为 r,树的高度为 h,内部结点数为 n。根据性质可推导出:
- h ≤ 2r


