Splay学习笔记

article/2025/11/9 15:57:17

昨天这个时候到现在终于把Splay给搞明白了,还A了一道郁闷的出纳员;刚学完的感受:我再也不碰这东西了;做完郁闷的出纳员的感受:我发誓这辈子不当出纳员(虽然这确实只是个入门题……)
于是来讲一讲这个恶心的东西吧……(全程不用指针,请做好心理准备……)
学习前请先学习下二叉搜索树,里面可能直接用到这个东西
首先,Splay是一个数据结构,为了突出它是一个数据结构,所以给他开个结构体……

struct tree
{int val,sz,cnt;//val为值 sz为子树大小,cnt为"有多少这个值"//cnt:假如出现了两个一模一样的值,只需要让cnt+1就可以了,cnt是数目int s[2],f;//s[0]为左儿子 s[1]为右儿子 f为父亲
};

为了之后的操作,我们再写三个函数(如果认为没用可以先跳过,过一会用到了再回来看)

bool son(int x) //返回x是左儿子还是右儿子,如果为左儿子,返回0,右儿子则返回1
{return a[a[x].f].s[1] == x;
}void rejs(int x)    //重新计算以x为根,子树的大小,子树大小等于左子树大小加右子树大小(好吧我承认我英语拙计)
{a[x].sz = a[a[x].s[0]].sz + a[a[x].s[1]].sz + a[x].cnt;
}void point(int x,int y,bool z)  //在x下面插入y,y是x的z儿子(z为0则左儿子,z为1为右儿子)
{a[x].s[z] = y;a[y].f = x;
}

写完这几个树的基本函数,我们要开始讲splay啦(似乎我之前好像真的没有开始讲splay)
Splay最重要的一个操作就是旋转(rotate),如下,(图片为1600x900,可直接作为桌面):
这里写图片描述
我们的目的是将红色节点旋转到它父亲的位置,即黄色节点的位置
我们应当怎么办呢?不要急,看组图
这里写图片描述
bool型变量son(黄)代表黄色节点是左儿子还是右儿子
将红色节点接到黄色节点的父亲(也就是绿色节点)的下面,是绿色节点的son(黄)儿子,也就是说代替了黄色节点;
黄色节点被代替了怎么办?再开个变量记录一下即可
这里写图片描述
bool型变量son(红)代表红色节点是左儿子还是右儿子
把红色节点的son(红)&1儿子(图中的蓝色节点,蓝色节点和父亲关系和红色节点和父亲关系正好相反)接到黄色节点下面,是黄色节点是son(红)儿子,代替了红色节点;
这里写图片描述
最后把黄色节点的父亲改为红色节点,旋转完成!
旋转完成后:
这里写图片描述
(我再也不用PS画这玩意了……)

void rot(int x)
{int p = a[x].f;bool d = son(x);point(a[p].f,x,son(p));point(p,a[x].s[d^1],d);point(x,p,d^1);rejs(p);rejs(x);if(a[x].f == 0)root = x;//root是根节点的编号
}

这就是Splay的核心操作——rotate,它的时间复杂度是——O(1)
然而学会了有什么用呢= =,下面来讲Splay的其他操作及如何平衡
首先是Splay的插入操作,Splay每插入一个新节点,就把这个节点强制旋转到根节点,如何强制旋转到根节点呢?如果while(不是根节点)rotate(x)的话就有可能退化成一条链……于是Splay“贴心”的为我们准备了splay操作……
splay操作的目的是将一个点旋转到根节点,这个操作是这样的:
1.如果这个点是根节点,那么你可以直接退出了……
2.如果这个点的父亲是根节点,那么就直接把这个点rotate上去……
3.如果上述两条均不满足,那么分类讨论:
(1)设son(x)为这个和父亲节点的关系,son(f)为父亲节点和爷爷节点的关系
(2)如果两个关系相同(均为左儿子或均为右儿子),那么就先rotate父亲节点,然后rotate这个节点
(3)如果两个关系不同(一个是左儿子一个是右儿子),那么就把这个节点连续rotate两次

void splay(int x)
{while(a[x].f != 0){if(a[a[x].f].f == 0)rot(x);else{if(son(x) == son(a[x].f)){rot(a[x].f);rot(x);}else{rot(x);rot(x);}}}
}

这样就可以写出插入操作了,还记得插入操作怎么做吗?插入一个节点然后splay到根节点

void ins(int x)
{int w = root,f = 0;int p = findn(x);if(p)//如果这个值已经存在,那么就直接给这个节点+1吧{a[p].cnt ++;while(p != root){rejs(p);p = a[p].f;}rejs(root);return ;}while(w){f = w;if(x < a[w].val)w = a[w].s[0];elsew = a[w].s[1];}//这是前半部分,和普通的二叉查找树插入方法一样,我承认我打的很丑……a[++tot].val = x;a[tot].cnt = 1;//新建节点,标号为totif(f == 0)//如果这个点是根节点的话,直接插入即可……{root = tot;rejs(root);return ;}//否则插入这个节点并spaly到根节点if(x < a[f].val)point(f,tot,0);elsepoint(f,tot,1);splay(tot);
}

然后是删除操作,Splay的删除操作比较丧病,我只讲一下我的写法吧……
设要删除的节点为x,那么,首先splay一下x的前驱,然后splay一下x的后继,啥?你前驱和后继还不会写???好吧好吧,我讲……
x的前驱是指小于x且最大的节点,后继就是大于x且最小的节点
前驱就是在x的左子树上一直往右跑,如果没有左子树那就往上找
后继就是在x的右子树上一直往左跑,如果没有右子树那也往上找
自行yy可解

int near(int x,bool d)
{if(a[x].s[d] != 0){int p = a[x].s[d];while(a[p].s[d^1])p = a[p].s[d^1];return p;}else if(son(x) == d^1)return a[x].f;else{int p = a[x].f;while(son(p) == d){if(p == root)return 0;p = a[p].f;}return a[p].f;}
}

接着继续我们的删除操作,删除操作就是上面讲的:splay(x的前驱),splay(x的后继),然后x的后继变为根节点,x的前驱变为根节点的左儿子,x到哪里了呢?
x成为了x前驱的右子树!直接砍掉这个右子树就ok啦~(如果删除区间也可以这样做,splay区间左边界的前驱,splay区间右边界的后继,整个区间就变成了区间左界前驱的右子树~(≧▽≦)/~)

void cle(int x)//cle操作是清除一个点,没有也无所谓吧
{a[a[x].f].s[son(x)] = 0;a[x].val = 0;a[x].sz = 0;rejs(a[x].f);a[x].f = 0;
}void del(int x)
{int p = near(x,0);int q = near(x,1);if(!p || !q){splay(x);if(p == 0){root = a[x].s[1];a[a[x].s[0]].f = 0;}else{root = a[x].s[0];a[a[x].s[0]].f = 0;}return ;}splay(p);splay(q);rot(p);cle(x);
}

至此你终于获得了一棵可用的splay,拿去乱搞吧!


http://chatgpt.dhexx.cn/article/vrJNgpQp.shtml

相关文章

[Splay伸展树]splay树入门级教程

首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角。。 PS:若代码有误,请尽快与本人联系,我会尽快改正 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGang,不知道是不是因为和某位大牛…

Splay Tree(伸展树)

二叉查找树&#xff08;Binary Search Tree&#xff09;能够支持多种动态集合操作。因此&#xff0c;在信息学竞赛中&#xff0c;二叉排序树起着非常重要的作用&#xff0c;它可以被用来表示有序集合、建立索引或优先队列等。 作用于二叉查找树上的基本操作的时间是与树的高度…

浅谈splay

例题&#xff1a; 给出一个长度为n序列a。 有m次操作&#xff0c;每次操作可以修改a[i]&#xff0c;在第i个数前插入一个数x&#xff0c;或查询区间[l,r]的最大值。 1≤n≤100000,1≤m≤100000。 强制在线 看到这道题最自然的反应就是用线段树&#xff0c;但有了插入操作线段树…

关于splay的一些说明

前言splay出现的背景它的操作 push_uprotatesplayfindinsertnextdeletefindkthmain 前言 暑假快过完了,大家感觉是不是很棒!gay房也体验过最新的断电模拟器了. 好吧,在开讲之前我还是得说一个.刀剑神域的外传实在太好看了! 除了精彩的战斗场面,神一般的人设和强大的剧情,比…

Splay入门详解

Splay入门详解 写在前面 听说平衡树是一种强大的数据结构&#xff0c;听同年级或高年级大佬们讲起来也感觉很牛笔的亚子&#xff0c;而最近XC又叫我们去学习一下 L C T LCT LCT&#xff01;&#xff1f; 又因为 S p l a y Splay Splay是学习 L C T LCT LCT的基础&#xff0c;…

【学习笔记】Splay

普通平衡树 模板题链接 1、引入 一种二叉树&#xff0c;这棵树满足任意一个节点&#xff0c;它的左儿子的权值<自己的权值<右儿子的权值 这种树叫做二叉查找树&#xff0c;这个概念应该在初赛中见过了吧 Splay就是利用这个结构来实现的 2、变量 模板题的7大变量 s…

平衡树详解(Splay)

引入 先看例题&#xff1a;&#xff08;洛谷 P3369 【模板】普通平衡树&#xff09; 您需要写一种数据结构&#xff0c;来维护一些数&#xff0c;其中需要提供以下操作&#xff1a; 1.插入 x x x 数 2.删除 x x x 数(若有多个相同的数&#xff0c;因只删除一个) 3.查询 x x…

Splay入门解析【保证让你看不懂(滑稽)】

upd&#xff1a;忽然发现直接在百度上搜索 splay s p l a y 就会搜索到我这篇文章&#xff1f;小蒟蒻瑟瑟发抖。 因为CSDN这边我基本不会看回复什么的&#xff0c;所以如果有问题还是请移步cnblogs里面吧 Cnblogs里面这篇文章的链接 BST真是神奇的东西。。。 而且种类好多呀…

Splay Tree

类别&#xff1a;二叉排序树 空间效率&#xff1a;O(n) 时间效率&#xff1a;O(log n)内完成插入、查找、删除操作 创造者&#xff1a;Daniel Sleator和Robert Tarjan 优点&#xff1a;每次查询会调整树的结构&#xff0c;使被查询频率高的条目更靠近树根。 注&#xff1a;所有…

【算法详解】splay的初步了解

qwq表示最近感受到了不停课的鸭梨啊&#xff0c;好难搞啊……算法太难学了……我好菜啊qwq 其实半个多月前就可以写这篇文章&#xff0c;不过由于时间紧张没写emmmmmm&#xff0c;不扯闲言乱语了&#xff0c;如果有什么写的不好的地方凑活一下吧2333333333 splay是一种可以使树…

splay详解

一&#xff1a;什么是splay&#xff08;伸展树&#xff09; 首先了解二叉排序树 二叉排序树或者是一棵空树&#xff0c;或者是具有下列性质的 二叉树&#xff1a; &#xff08;1&#xff09;若左子树不空&#xff0c;则左子树上所有结点的值均小于或等于它的 根结点的值&#…

Splay 总结基础精华

前言&#xff1a; 第一次学习Splay是2月份&#xff0c;打板子的时候是3月份&#xff0c;Ac是4月份&#xff0c;写这篇博客是6月初&#xff1b;原因是因为我竟然发现我忘了Splay的板子了&#xff01;很慌&#xff0c;必须总结一下&#xff01; 不敢说是最详细的&#xff0c;但希…

关系型数据库与非关系型数据库详解

关系数据库与非关系型数据库 一、数据库概述1、关系型数据库2、非关系型数据库 二、数据库区别1、数据存储方式不同2、扩展方式不同3、对事务性的支持不同 三、非关系型数据库产生背景四、Redis简介1、Redis 优点 五、Redis 安装部署六、Redis 命令工具&#xff08;1&#xff0…

关系型数据库RDS基本简介

OSS存放非结构化的数据&#xff0c;如&#xff1a;音频、视频、图片 rds存放结构化的数据&#xff0c;如&#xff1a;一张表&#xff0c; RDS产品概要 可以根据业务的需求进行弹性伸缩。 采用主从备份架构&#xff0c;三节点数据存储&#xff0c;具备高可用性和数据可靠性 …

2 关系型数据库是什么?

目录结构 关系型数据库基本概念结构化查询语言数据定义语言&#xff08;DDL&#xff09;数据查询语言&#xff08;Data Query Language, DQL&#xff09;数据操纵语言&#xff08;Data Manipulation Language, DML&#xff09;数据控制语言&#xff08;Data Control Language, …

常见的关系型数据库有哪些

Oracle Database&#xff1a;由Oracle公司开发和维护的商业关系型数据库&#xff0c;具有广泛的应用场景和功能。 MySQL&#xff1a;开源关系型数据库&#xff0c;常用于Web应用程序和小型企业应用。 Microsoft SQL Server&#xff1a;由Microsoft公司开发和维护的商业关系型…

Bezier曲线快速相交计算(含代码)

Bezier曲线快速相交计算 背景介绍算法思路解释和分析示例参考资料 背景介绍 很多时候&#xff0c;需要计算曲线段与曲线段是否有交点。常规的思路是直接联立方程求解。不过&#xff0c;直接求方程的解这种思路通常在计算上开销较大。 针对任意曲线&#xff0c;曲线的方程阶次…

js绘制贝塞尔曲线(Bézier-Curve)

贝塞尔曲线(Bzier curve)&#xff0c;又称贝兹曲线或贝济埃曲线&#xff0c;是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线&#xff0c;贝兹曲线由线段与节点组成&#xff0c;节点是可拖动的支点&#xff0c;线段像可伸缩的皮筋&#xff0c;我们…

Bezier曲线与B-Spline曲线

微分几何基础 微分集合是用微分的方法来研究曲线的局部性质&#xff0c;如曲线的弯曲程度等。 一条可以用参数表示的三维曲线是一个有界点集&#xff0c;可以写成一个带参数的、连续的、单值的数学函数&#xff1a; { x x ( t ) y y ( t ) z z ( t ) 0 ⩽ t ⩽ 1 p p ( t…

初识贝塞尔(bezier)曲线

文章目录 资料援引贝塞尔曲线的用途一阶贝塞尔&#xff08;bezier&#xff09;曲线二阶贝塞尔&#xff08;bezier&#xff09;曲线三阶贝塞尔&#xff08;bezier&#xff09;曲线高阶贝塞尔&#xff08;bezier&#xff09;曲线三阶贝塞尔曲线求插值&#xff08;Slerp&#xff0…