【学习笔记】【算法】【施工ing】Splay

好吧,Splay 还是要学的。

定义

Splay 是一种平衡 BST(二叉搜索树),通过伸展操作不断将某个节点旋转到根节点,使得整棵树既能满足 BST 的性质,又可以保证树不会退化为链。

而 Splay 的核心,就是在如何实现把点搬到根的这一操作。

Splay 的复杂度是 O(logn),证明不重要所以

基本操作

  • pushup(x) 不用解释吧,就是更新 size

  • get(x) 判断 x 是其父亲的哪个儿子。

  • clear(x) 销毁 x
void pushup(int x) { siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x]; }

bool get(int x) { return x == ch[fa[x]][1]; }

void clear(int x) { ch[x][0] = ch[x][1] = fa[x] = val[x] = siz[x] = cnt[x] = 0; }

rotate 操作

为了使 Splay 保持平衡而进行旋转操作,旋转的本质是将某个节点上移一个位置。

旋转需要保证:

  • 整棵 Splay 的中序遍历不变,即不能破坏二叉查找树的性质。
  • 受影响的节点维护的信息依然正确有效。
  • root 必须指向旋转后的根节点。

旋转分两种,左旋与右旋,也叫 zig 和 zag。

image

具体分析,以 zig 为例,设需要旋转的节点为 x,其父亲为 y

  • y 的左儿子改为 x 的右儿子,且若 x 有右儿子,将其的父亲改为 y

  • x 的右儿子改为 y,也把 y 的父亲改为 x

  • 若原来的 y 还有父亲 z,那把 z 的儿子替换为 x

void rotate(int x) {
  int y = fa[x], z = fa[y], chk = get(x);
  ch[y][chk] = ch[x][chk ^ 1];
  if (ch[x][chk ^ 1]) fa[ch[x][chk ^ 1]] = y;
  ch[x][chk ^ 1] = y;
  fa[y] = x;
  fa[x] = z;
  if (z) ch[z][y == ch[z][1]] = x;
  pushup(y);
  pushup(x);
}

Splay 操作

将一个节点 x 旋转到根节点。

Splay 操作分为三种,具体六个情况,设当前点为 x,其父亲为 p,父亲的父亲是 g

  • zig/zag 在 p 为根节点时,用 zig/zag 来将 x 旋到根上,只有刚好在 Splay 操作的点是奇数深度时在最后一步做一次。

image

  • zig-zig/zag-zag 在 p 并非根节点且 xp 同边时操作。两次都对 x 操作,如下图:

image

  • zig-zag/zag/zig 在 p 并非根节点且 xp 并不同边时操作。如下图:

image

posted @   ayaka0928  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示