首页 > 其他分享 >[学习笔记] splay

[学习笔记] splay

时间:2024-12-24 18:34:19浏览次数:4  
标签:node 学习 zig zag 笔记 splay fa lson now

前置:二叉查找树

在二叉查找树上做许多操作都十分方便。然而递归树的层数意味着时间复杂度为树高级别。当树是链状时,时间复杂度会退化。各类平衡树的存在大都为了使二叉查找树“平衡”,即高度不会超过 \(\log n\)(\(n\) 为树的结点个数)。如此以来,在二叉查找树上的操作就有了时间复杂的的保证。

splay 伸展树

平衡树的一种。splay 通过保证树的有序性的前提下的旋转来完成操作 & 保证树的平衡。

基本操作

1.左旋(zag)

设要左旋的节点为 \(x\),其父亲节点为 \(y\)。则一次左旋操作会造成以下影响:

  1. 将 \(y\) 设为 \(x\) 的右儿子。
  2. 将 \(x\) 的原右儿子设为 \(y\) 的左儿子。

2.右旋(zig)

与左旋相反。将 \(x\) 左旋后的树的右旋后的结果即为原树。

  1. 将 \(y\) 设为 \(x\) 的左儿子。
  2. 将 \(x\) 的原左儿子设为 \(y\) 的右儿子。

code:

void zig(node *x)
{
	node *y=x->fa;
	node *z=y->fa;
	y->lson=x->rson;
	if(x->rson!=null)
		x->rson->fa=y;
	update(y);
	x->rson=y;
	y->fa=x;
	update(x);
	x->fa=z;
	if(z!=null)
	{
		if(z->lson==y)z->lson=x;
		if(z->rson==y)z->rson=x;
	}
}
void zag(node *x)
{
	node *y=x->fa;
	node *z=y->fa;
	y->rson=x->lson;
	if(x->lson!=null)
		x->lson->fa=y;
	update(y);
	x->lson=y;
	y->fa=x;
	update(x);
	x->fa=z;
	if(z!=null)
	{
		if(z->rson==y)z->rson=x;
		if(z->lson==y)z->lson=x;
	}
}

左旋 / 右旋后的树依旧满足二叉搜索树的性质。可手动模拟确认。

核心操作

伸展操作 \(\texttt{splay(x,s)}\)

\(\texttt{splay(x,s)}\) 的含义是:将 \(x\) 结点旋转至 \(s\) 的儿子节点的位置。当 \(s=0\) 时,将 \(x\) 旋转至根节点。

实现:设当前 \(x\) 的父亲是 \(y\),\(y\) 的父亲是 \(z\)。

情况一:\(y=s\)。即 \(x\) 的父亲即为目标,当 \(x\) 为 \(y\) 的左儿子,进行一次 zig 操作。当 \(x\) 为 \(y\) 的右儿子,进行一次 zag 操作。

则 \(\texttt{splay(x,s)}\) 完成。

情况二:\(y≠s\),且 \(x\) 与 \(y\) 皆为其父亲的左 / 右儿子,则进行 zig-zig (即两次右旋)操作或 zag-zag (即两次左旋)操作。

情况三:\(y≠s\),且 \(x\) 与 \(y\) 一个为父亲的左儿子,一个为父亲的右儿子。当 \(x\) 为 \(y\) 的左儿子且 \(y\) 为 \(z\) 的右儿子,则进行 zig-zag 操作。当 \(x\) 为 \(y\) 的右儿子且 \(y\) 为 \(z\) 的左儿子,则进行 zag-zing 操作。

code:(细节自行参悟)

void splay(node *x,node *aim)
{
	while(x->fa!=aim)
	{
		node *y=x->fa;
		node *z=y->fa;
		bool p1=(x==y->lson);
		bool p2=(y==z->lson);
		if(z==aim)
		{
			if(p1)zig(x);
			else zag(x);
		}
		else
		{
			if(p1&&p2)zig(y),zig(x);
			if((!p1)&&(!p2))zag(y),zag(x);
			if(p1&&(!p2))zig(x),zag(x);
			if((!p1)&&p2)zag(x),zig(x);
		}
	}
	if(x->fa==null)root=x;
}

基于核心操作的扩展操作

在这里进行概念的一个明确:splay 所依靠的二叉搜索树可以以下标 / 权值为关键字,这样有不同的效果。然而大部分二叉搜索树以权值为关键字。

前驱

寻找小于 \(x\),且最大的数。从根节点开始遍历,如果当前节点的值小于要查找的值,则往右子树遍历。否则往左子树遍历。

code:

node* pred(int val,node *now,node *opt)
{
	if(now==null)return opt;
	if(now->val<val)
		return pred(val,now->rson,now);
	return pred(val,now->lson,opt);
}

后继

寻找大于 \(x\),且最小的数。从根节点开始遍历,如果当前节点的值大于要查找的值,则往左子树遍历。否则往右子树遍历。

code:

node* succ(int val,node *now,node *opt)
{
	if(now==null)return opt;
	if(now->val>val)
		return succ(val,now->lson,now);
	return succ(val,now->rson,opt);
}

标签:node,学习,zig,zag,笔记,splay,fa,lson,now
From: https://www.cnblogs.com/WindChime/p/18628460

相关文章

  • [学习笔记] 二项式定理与反演
    一假设\(f(x)\)代表恰好满足\(x\)个性质的方案数。钦定代表至少\(x\)个。假设\(g(x)\)代表至多满足\(x\)个性质的方案数。显然有\[g(n)=\sum_{i=0}^n\left(\begin{matrix}n\\i\end{matrix}\right)f(i)\]并且有\[f(n)=\sum_{i=0}^n\left(\begin{matrix}n\\i\end{ma......
  • [学习笔记] 字典树
    https://blog.csdn.net/qq_49688477/article/details/118879270字典树图文详解就是根据“查字典”的思想使用c++实现罢了。比如要查一个单词\(\texttt{fAKe}\),先在根节点中查找\(\texttt{f}\),找不到则没有这个单词。找到了就来到\(\texttt{f}\)的节点往下查找\(\texttt{......
  • [学习笔记] 根号分治
    https://www.cnblogs.com/guanlexiangfan/p/15553329.htmlhttps://blog.csdn.net/qq_35684989/article/details/127190872放一下讲得比较好的根号分治。根号分治,一般将数据分为\(a<\sqrtn\)的与\(a>\sqrtn\)的进行分类讨论。一般可以配合预处理将\(O(n^2)\)的做法优化......
  • [学习笔记] 线性筛与欧拉函数
    一线性筛主要讲下思想,埃氏筛法就是用所有质数标记所有倍数,这样的时间复杂度是\(O(n\logn\logn)\),有两只\(\log\)。可是我不想要\(\log\),于是欧拉筛:改进:存下质数表。对于每一个数,只标记自己与不超过自己最小质因子的数的乘积,对于质数表\(2,3,5\),循环到\(i=6\)时,只筛去\(......
  • [学习笔记] 网络流
    网络流,梳理一下然后看下trick。网络流主要难点在于建模,网络流很多trick现在已经很难有新意了。很多很好想的都是紫题,没啥含金量啊。最大流在残量网络中找到一条路径,设边集为\(u\),要求满足\(\min_{x\inu}C_x≠0\),即每条边残量皆不为\(0\)。此时将这条路径流满,流量就......
  • 【学习笔记】平衡树
    介绍平衡树是一种特殊的二叉树搜树,他能在被修改后,依靠分裂,合并,等操作使得树能始终保持平衡(每一个节点的两棵子树的大小尽量相等),这里主要讲解FHQtreap。操作FHQtreap也叫无旋treap,他的每个节点有两个值\(val,pri\),其中\(pri\)满足二叉堆的性质,而\(val\)满足BST的性质......
  • 从实战的角度分析渗透测试究竟需要学习了解的知识点,黑客技术零基础入门到精通教程建议
    前言最近有很多人询问,自己明明OWASPTop10都学的差不多了,各种靶场也复现的差不多了,Burpsuite、goby、awvs、dirsearch等等工具也是用的丝滑,但为什么就是感觉挖不到洞呢基础知识已经准备的差不多了,现在可能缺乏的是挖洞时间的思路,针对特定场景下的渗透套路,这个一般可以学......
  • 机器学习:线性回归:最小二乘法应用一元线性回归(持续更新)
    目录前言(基础知识的准备最小二乘法在回归中的应用)利用最小二乘法解决最简单的一元线性回归问题第一步:引入必要的库并且创建数据集(这里使用的例子是房价与面积的关系)第二步利用某些方法去用一条直线去拟合你的数据第三步观察与测评求出的W,B值与数据集的拟合程度并且......
  • 机器学习:线性回归:梯度下降法应用多元线性回归(持续更新)
    目录第二节梯度下降法在线性回归中的应用情景带入这里提出误差函数即残差函数的概念:我们这里采用MSE损失函数来刻画预测值与真实值之间的误差大小下面是基于梯度下降法求解线性回归方程中参数(θ)(θ)的推导过程:于是我们重复的过程是:我们先观察各个特征数据与房价的......
  • 常见的机器学习算法,包含监督学习、无监督学习、半监督学习和强化学习
    一、监督学习算法(约70个)线性回归(LinearRegression)简单线性回归:用于建立一个自变量和一个因变量之间的线性关系,例如根据房屋面积预测房价,其模型表达式为\(y=\beta_0+\beta_1x+\epsilon\),其中\(y\)是因变量(房价),\(x\)是自变量(房屋面积),\(\beta_0\)和\(\beta_1\)是模型参数,\(\ep......