首页 > 其他分享 >Splay学习笔记

Splay学习笔记

时间:2023-09-09 18:11:24浏览次数:38  
标签:学习 ch 位置 笔记 儿子 Splay fa flag rotate

这已经是第三次学习 Splay 了

图片内容转载自 yyb 的博客

二叉搜索树

本来是一颗二叉树,但是满足这样的条件:

对于一个节点 \(x\), 满足它的左子树中所有节点的 \(val\) 都小于 \(val_x\),右子树中的所有节点的 \(val\) 都大于 \(val_x\)。

那么很显然,我们最希望它(尽可能)是一颗满二叉树,或者说深度为 \(logn\),这样可以做到在 \(\Theta(logn)\) 的时间内处理数列信息。

然而在很多时候,如果不加维护,在极端情况下它可能会变成这样:

那么这样我们查询一次就很可能会变成 \(\Theta(n)\),这是我们不希望看到的。

于是我们就有了很多很多树,来维护这个东西。

Splay

Splay 就是一颗二叉搜索树,或者说一种维护二叉搜索树的方式。

现在有一颗二叉搜索树:

\(X\)、\(Y\)、\(Z\) 都是平衡树上的节点,而 \(A\)、\(B\)、\(C\) 是一整棵子树,显然有:

\[A<X<B<Y<C<Z \]

现在我们想让 \(X\) 到 \(Y\) 的位置去,该怎么办呢?

首先把 \(X\) 直接放在 \(Y\) 的位置,现在 \(Y\) 没有地方去了。

然后因为 \(Y>X\),再把 \(Y\) 放在 \(X\) 的右儿子(\(B\))的位置,现在 \(B\) 没有地方去了。

最后因为 \(B<Y\),所以可以把 \(B\) 放在 \(Y\) 的左儿子上,注意到我们把 \(X\) 拿走了之后,\(Y\) 没有左儿子了,所以现在这棵树的每个点都有了自己的归属。

于是这棵树变成了这样:

这就是 rotate 的基本操作,但是这只是一种情况。

现在来分类讨论,一共四种情况:

  1. \(X\) 是 \(Y\) 的左儿子,\(Y\) 是 \(Z\) 的左儿子
  2. \(X\) 是 \(Y\) 的左儿子,\(Y\) 是 \(Z\) 的右儿子
  3. \(X\) 是 \(Y\) 的右儿子,\(Y\) 是 \(Z\) 的左儿子
  4. \(X\) 是 \(Y\) 的右儿子,\(Y\) 是 \(Z\) 的右儿子

对于每一种情况,简单转一转可以发现一个普遍的规律,也就是 rotate 的整个过程:

  1. 初始化
int y=t[x].fa,z=t[y].fa;
bool flag=(x==t[y].ch[1]);
  1. 把 \(X\) 放在 \(Y\) 的位置,现在 \(Y\) 没有地方放了
t[z].ch[y==t[z].ch[1]]=x,t[x].fa=z;
  1. 把 \(Y\) 放在 \(X\) 的 \(X\) 对于 \(Y\) 的那个儿子的相对的那个儿子的位置,原来处在那个位置的节点记为 \(t\)
t[x].ch[flag^1]=y,t[y].fa=x;
  1. 把 \(t\) 放在 \(Y\) 的 \(X\) 对于 \(Y\) 的那个儿子的位置,那个位置原本属于 \(X\) 而它现在空出来了,可以直接填进去
t[y].ch[flag]=t[x].ch[flag^1];
if(t[x].ch[flag^1])t[t[x].ch[flag^1]].fa=y;//需要注意这里可能 X 根本没有这个儿子

这只是示意代码,但是为了防止需要的信息被提前更新掉,应该把 \(2\)、\(3\) 的位置交换:

inline void rotate(int x)
{
    int y=t[x].fa,z=t[y].fa;
    bool flag=(x==t[y].ch[1]);
    t[z].ch[y==t[z].ch[1]]=x;t[x].fa=z;
    t[y].ch[flag]=t[x].ch[flag^1];
    if(t[x].ch[flag^1])t[t[x].ch[flag^1]].fa=y;
    t[x].ch[flag^1]=y,t[y].fa=x;
    return;
}

然后有了 rotate 操作,我们就可以在保证平衡树结构的前提下,任意改变节点的位置了。

直接说结论:

  • 如果 \(X\) 对于 \(Y\) 的儿子的位置与 \(Z\) 对于 \(X\) 的位置不同,则 rotate(x)
  • 如果 \(X\) 对于 \(Y\) 的儿子的位置与 \(Z\) 对于 \(X\) 的位置相同,则 rotate(y)

最后再 rotate(x),直到 \(X\) 到达指定位置,最后如果是改变到根,就要更新根的编号。

inline void splay(int x,int goal)
{
    while(t[x].fa!=goal)
    {
        int y=t[x].fa,z=t[t[x].fa].fa;
        if(z!=goal)(y==t[z].ch[1])^(x==t[y].ch[1])?rotate(x):rotate(y);
        rotate(x);
    }
    if(!goal)root=x;
    return;
}

以上就是 Splay 的核心操作,其他的任何操作都只需要以二叉搜索树为基础,利用其性质进行询问(操作)即可。

标签:学习,ch,位置,笔记,儿子,Splay,fa,flag,rotate
From: https://www.cnblogs.com/Endline/p/17684905.html

相关文章

  • Markdown语言学习总结(软件:Typora)
    Markdown1.标题:#+标题——一级标题##+标题——二级标题###+标题——三级标题####+标题——四级标题#####+标题——五级标题######+标题——六级标题最多到六级标题2.字体**加粗**加粗*斜体*斜体***斜体加粗***斜体加粗~~删......
  • 关于软件架构设计的小笔记
    设计良好的计算机软件应该是易于扩展,同时抗拒修改。这就是著名的开闭原则(OCP)。换句话说,一个设计良好的计算机系统应该在不需要修改的前提下就可以轻易被扩展。其实这也是我们研究软件架构的根本目的。如果对原始需求的小小延伸就需要对原有的软件系统进行大幅修改,那么这个系统......
  • C#学习日记
    2023年9月9日工具visualstdio2019窗口名称修改lable标签button点击事件点击换颜色formLearn.ActiveForm.BackColor=Color.Green;点击弹窗MessageBox.Show("这是点击弹窗的内容");所有的事件和行为需要在属性/事件窗口中进行绑定designer.cs内容(自......
  • 学习内容
    AD画图,画封装,画symbol,导出网表,导出BOM,allegro画图,画symbol,导出网表,导出BOM。ADS通道仿真HyperlynxSI仿真,链路仿真阻抗计算,叠层计算设计DDR4走线规则serdes走线规则CPU小系统FPGAVerilog设计,SDC约束编写,调试。PCIE,USB走线设计 ......
  • 2023-09-09学习记录
    NettyUnpooled疑惑Netty中的Unpooled类,ByteBufhttps://www.jianshu.com/p/dc7782cb31fcNettyChannelGroup疑惑ChannelGroup详解https://www.jianshu.com/p/0fead0912ef3Netty心跳知识点IdleStateHandleruserEventTriggered疑惑Netty实现心跳......
  • 《信息安全系统设计与实现》第一周学习笔记
    《信息安全系统设计与实现》第一周学习笔记一、知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图第一章关于本书涵盖Unix/Linux的所有基本组件,包括进程管理、并发编程、定时器和时钟服务、文件系统、网络编程和MySQL数据......
  • qemu中的glib库api试用--Apple的学习笔记
    一,前言qemu中有些glib库的api,我想学习试用下。二,编译及调试1.     使用glib库后编译报错,缺少头文件root@ubuntu:/work/study#gcct1.c-ot1t1.c:2:18:fatalerror:glib.h:Nosuchfileordirectory#include<glib.h>^compilationterminated.2.......
  • 虚化及信息安全学习历程--Apple的学习笔记
    一,前言先做了一个基本方向的定义,然后我就开始玩qemu,基于qemu做二次开发。在学习qemu的过程中主要学习hypervisor,然后再学习信息安全相关内容。二,过程记录tbd三,新路历程2023/09/01:开学咯,之前的blog我写了5年,由于不好用,所以我换了blog同时也换了新的学习大方向,正好再来一个5年。 ......
  • Python基础学习day07
    昨日内容回顾基本数据类型列表(list)1.能够存储多个数据,且可获取单个或整体数据2.中括号括起来[],里面可以存放多个且不同数据类型的数据(包括列表),各个数据用逗号隔开3.索引取值:#索引通常是从0开始L1=[11,12,13,[14,15,16],17]print(L1[3])#出来的结果是14,15,16字典(dict)1.能......
  • 搭建内网学习所需要的环境(详细)
    搭建内网学习所需要的内网环境(详细)前言建议内存加为24G或32Gwindows2012R2192.168.1.1(域控制器)密码windows2012其他计算机登录域HACKER\testuserAdmin@123其他计算机加入域Administratorwindows2012域hacker.testlabwindows2008R2192.168.1.2密......