Splay
SkyDreamer · · 算法·理论
定义
Splay 树,是一种平衡二叉查找树,它通过 伸展(splay)操作,不断将某个节点旋转到根节点,使得整棵树仍然满足二叉查找树的性质,能够在均摊
基本结构与操作
Splay 树是一棵二叉查找树,查找某个值时满足性质:左子树任意节点的值
维护信息
| 本文使用数组模拟指针来实现 Splay 树,需要维护如下信息: | |||||||
|---|---|---|---|---|---|---|---|
| 根节点编号 | 已使用节点个数 | 父亲 | 左右儿子编号 | 节点权值 | 权值出现次数 | 子树大小 |
辅助操作
首先是一些简单的辅助操作:
bool dir(int x){
return x==son[fa[x]][1];
}
void push_up(int x){
sz[x]=cnt[x]+sz[son[x][0]]+sz[son[x][1]];
}
旋转操作
为了使 Splay 保持平衡,需要进行旋转操作。旋转的作用是将某个节点上移一个位置。
旋转需要保证:
- 整棵 Splay 的中序遍历不变(不能破坏二叉查找树的性质);
- 受影响的节点维护的信息依然正确有效;
-
在 Splay 中旋转分为两种:左旋和右旋。
观察图示可知,如果要通过旋转将节点
具体分析旋转步骤:(假设需要上移的节点为
- 首先,记录节点
x 的父节点y ,以及y 的父节点z (可能为空),并记录x 是y 的左子节点还是右子节点; - 按照旋转后的树中自下向上的顺序,依次更新 y 的左子节点为
x 的右子节点,x 的右子节点为y ,以及若z 空,z 的子节点为x ; - 按照同样的顺序,依次更新当前
y 的左子节点(若存在)的父节点为y ,y 的父节点为x ,以及x 的父节点为z ; - 自下而上维护节点信息。