基本思想: 每个节点被访问时,使用旋转操作将其移动到根。
旋转是自底向上的,因此需要设置父亲指针
核心操作:伸展
Splay(x)保持伸展树有序性的前提下,将元素x调整到树的根部
单次双旋,分若干种情况讨论
!p->father x==y->left Zig(x)
- x==y->right Zag(x)
p->father (令p=x->father)
- x==p->left
- p==p->father->left Zig(p) Zig(x)
- p==p->father->right Zig(x) Zag(x)
- x==p->right
- p==p->father->left Zag(x) Zig(x)
- p==p->father->right Zag(p) Zag(x)
伸展操作:不断重复的双旋
while ((p=x->father)!=NULL) DoubleRotate;
接口实现:五种基本操作
Search 查找 正常Search以后Splay
Insert 插入 正常Insert以后Splay
Merge 合并 设待合并集合为A,B,首先伸展A中的最大元素,然后将B作为它的右子树
Split 分裂 对分裂中心进行伸展,那么它的左右子树就是分裂后的两个集合
Delete 删除 首先以待删除元素作为中心进行分裂,然后对分裂结果进行合并
其它操作:伸展可能会提供更多便利
n个结点的伸展树m次操作的总时间开销为O(mlogn)。