伸展树(Splay Tree)¶
概述¶
伸展树(Splay Tree)是一种自调整二叉搜索树,无需显式维护平衡信息。每次访问(查找、插入、删除)后,将访问的节点通过旋转移动到根节点位置,使得频繁访问的节点靠近树根,利用访问局部性提高效率。
核心思想:不保证每次操作都是 O(log n),但保证 m 次操作的总时间为 O(m log n + n),即摊还时间复杂度为 O(log n)。
伸展树特点¶
| 特性 | 说明 |
|---|---|
| 自调整 | 无需显式平衡信息(高度、颜色等) |
| 访问局部性 | 频繁访问的节点自动靠近根 |
| 摊还分析 | m 次操作总时间 O(m log n + n) |
| 简单实现 | 无需额外存储空间 |
| 分裂合并 | 支持高效的分裂和合并操作 |
伸展操作¶
伸展操作是将节点 x 旋转到根的过程,分为三种情况:
1. Zig(单旋转)¶
当 x 的父节点是根时,进行单旋转:
旋转前
y
x
A
B
C
→
旋转后
x
A
y
B
C
x 是 y 的左孩子,右旋
2. Zig-Zig(同侧双旋转)¶
当 x 和 x 的父节点都是左孩子(或都是右孩子)时:
旋转前
z
y
x
A
B
C
D
→
旋转后
x
A
y
B
z
C
D
x、y 都是左孩子,先右旋 z,再右旋 y
3. Zig-Zag(异侧双旋转)¶
当 x 是左孩子,x 的父节点是右孩子(或相反)时:
旋转前
z
A
y
x
B
C
D
→
旋转后
x
z
A
B
y
C
D
x 是左孩子,y 是右孩子,先左旋 y,再右旋 z
伸展操作可视化:
graph TB
subgraph Zig_Zig过程
z1(("z")) --> y1(("y"))
z1 --> d1(("D"))
y1 --> x1(("x"))
y1 --> c1(("C"))
x1 --> a1(("A"))
x1 --> b1(("B"))
end
subgraph 结果
x2(("x")) --> a2(("A"))
x2 --> y2(("y"))
y2 --> b2(("B"))
y2 --> z2(("z"))
z2 --> c2(("C"))
z2 --> d2(("D"))
end
style x1 fill:#4CAF50,color:#fff
style x2 fill:#4CAF50,color:#fff
伸展操作的作用:每次伸展后,被访问节点成为根,且伸展路径上的节点深度减半(摊还意义上),这是摊还分析的关键。
数据结构¶
| C | |
|---|---|
创建节点¶
旋转操作¶
左旋¶
右旋¶
旋转示意图¶
左旋
x
A
y
B
C
→
y
x
A
B
C
右旋
y
x
A
B
C
→
x
A
y
B
C