1. 伸展树介绍
伸展树(Splay Tree)是一种自调整的二叉搜索树,由 John Edward Hopcroft 和 Robert Endre Tarjan 于 1985 年提出。与 AVL 树不同,伸展树不要求严格的平衡,而是通过'伸展'操作将最近访问的节点移至根节点,利用局部性原理优化频繁访问的场景。
伸展树的旋转操作
每当访问(包括搜索、插入或删除)一个结点 s 时,伸展树就执行一次'展开'过程,将结点 s 移到二叉搜索树的根部。旋转有三种类型:
- 单旋转:被访问结点 s 的父结点是根结点时执行。s 成为新的根,原根 p 成为其子女。
- 一字形旋转:同构形状(如左 -左或右 -右)。先围绕 p 旋转 g,再围绕 s 旋转 p。
- 之字形旋转:异构形状(如左 -右或右 -左)。先围绕 s 旋转 p,再围绕 s 旋转 g。
伪代码描述如下:
void splaying(Node* g, Node* p, Node* s) {
// g 是 p 的父结点,p 是 s 的父结点。算法将 s 移到根结点位置
while (s != root) {
if (p == root) {
Rotate(s); // 单旋转
} else if ((g->left == p && p->left == s) || (g->right == p && p->right == s)) {
Rotate(p); Rotate(s); // 一字形双旋转
} else {
Rotate(s); Rotate(s); // 之字形双旋转
}
}
}
伸展树并不要求每一个操作都是高效的,但对于 n 个结点执行 m 次操作,总时间复杂度为 O(m log n),均摊时间复杂度为 O(log n)。
2. 红⿊树介绍
2.1 红⿊树的概念
红⿊树是一棵二叉搜索树,每个结点增加一个存储位表示颜色(红色或黑色)。通过对路径上结点颜色的约束,确保没有一条路径比其他路径长出 2 倍,因而是接近平衡的。
2.2 红⿊树的性质
- 根结点和所有外部结点(NIL)的颜色是黑色。
- 从根结点到外部结点的途中没有连续两个结点的颜色是红色。
- 所有从根到外部结点的路径上都有相同数目的黑色结点。
设从根到外部结点的路径长度为 PL,若 P 与 Q 是两条路径,则 PL(P) <= 2 * PL(Q)。红黑树的高度 h 满足 h <= 2 * log2(n + 1),因此增删查改的时间复杂度为 O(log n)。
2.3 红⿊树如何确保最⻓路径不超过最短路径的 2 倍的?
- 从根到 NULL 结点的每条路径都有相同数量的黑色结点,最短路径即全黑路径。
- 任意一条路径不会有连续的红⾊结点,最长路径为一黑一红间隔组成,长度约为最短路径的 2 倍。
- 综合性质,理论上的全黑最短路径和一黑一红的最长路径保证了高度限制。
2.4 红⿊树的效率
红黑树通过颜色约束间接实现了近似平衡。相对于 AVL 树,红黑树在插入相同数量结点时旋转次数更少,因为对平衡的控制没那么严格,但效率在同一档次。


