学习笔记:旋转treap

news/2025/1/1 16:23:02/文章来源:https://www.cnblogs.com/fush/p/18639440

前言

更好的阅读体验。
无旋 treap。
默认读者会 BST 的基本操作、堆和旋转。
本文旋转部分和上面那篇文章的相同。
代码中是小根堆。

思想

treap 既是一棵二叉查找树(tree),也是一个二叉堆(heap)。
但是如果这两个数据结构用同一个权值维护,那么这两种数据结构是矛盾的。
所以 treap 用了一个很巧妙的方式:给每个节点附加一个随机的优先级,让权值满足二叉查找树的结构,让优先级满足二叉堆的结构。
这个就是一棵 treap(黑色是权值,蓝色是随机的优先级):
tu
由于优先级只能随机赋予,堆不一定是一颗完全二叉树,,所以 treap 是弱平衡(近似平衡)的。

旋转

在不改变中序遍历的情况下,旋转可以改变树的结构。
在 treap 中,我们用旋转来满足二叉堆,控制树高。
图中从左到右是右旋,从右到左是左旋。
tu
我们来模拟一下右旋的过程(左旋同理)。
tu
在实现中,我会把左右旋放在一起写。

void rotate(int&now, int dir){  int t = d[now].ch[dir];  d[now].ch[dir] = d[t].ch[!dir];  d[t].ch[!dir] = now;  pushup(now), pushup(t), now = t;  //now 是 t 的儿子了,先更新 now 再更新 t
}  

这里的 rotate(x, 0) 表示将 \(ls_{x}\) 提到 \(x\) 的高度,即右旋。
这里的 rotate(x, 1) 表示将 \(rs_{x}\) 提到 \(x\) 的高度,即左旋。

基础操作

节点变化

我们要在定义的时候添加一个优先级,然后在新建时给他赋随机值。

//需要头文件 <random>,<chrono>    
std::mt19937 rd(std::chrono::steady_clock::now().time_since_epoch().count());  
struct node{  int ch[2], size, val, rank;  
}d[N];  
int newnode(int x){  int w = ++tot;  d[w].val = x, ls(w) = rs(w) = 0, d[w].size = 1, d[w].rank = rd();  return w;  
}  

插入

只有在插入的那个子树的优先级可能变化。
如果优先级比当前节点小,那么我们把它旋转上来。
记得更新节点。

void insert(int&now, int val){  if(!now)return void(now = newnode(val));  int dir = d[now].val < val;  insert(d[now].ch[dir], val);  if(d[d[now].ch[dir]].rank < d[now].rank)rotate(now, dir);  if(now)pushup(now);  
}  

删除

这里我们需要改变一下目标节点有两个儿子的时候的方法。
我们比较两个儿子的优先级,把优先级小的旋转上来。
那么目标节点就到当前节点的另一侧,继续删除即可。
返回时要更新节点。

void del(int&now, int val){  if(!now)return;  if(d[now].val == val){  if(ls(now) && rs(now)){  int z = d[rs(now)].rank < d[ls(now)].rank;//哪边的优先级小  rotate(now, z), del(d[now].ch[!z], val);//删除另一侧  }  else now = ls(now) ? ls(now) : rs(now);  }  else if(d[now].val < val)del(rs(now), val);  else del(ls(now), val);  if(now)pushup(now);//牢记  
}  

代码

P3369。

可持久化

不知道什么是可持久化的戳这。
只需要在所有要修改节点的地方新建节点,有注释的是新加句子。
完整代码。
修改片段:

void copynode(int &i){if(i)d[++tot] = d[i], i = tot;}//************  
void rotate(int&now, int dir){  int t = d[now].ch[dir];  copynode(t);//**************  now节点已经新建过了d[now].ch[dir] = d[t].ch[!dir];  d[t].ch[!dir] = now;  pushup(now), pushup(t), now = t;  }  void insert(int&now, int val){  copynode(now);//****************  if(!now)return void(now = newnode(val));  int dir = d[now].val < val;  insert(d[now].ch[dir], val);  if(d[d[now].ch[dir]].rank < d[now].rank)rotate(now, dir);  if(now)pushup(now);  }  void del(int&now, int val){  copynode(now);//****************  if(!now)return;  if(d[now].val == val){  if(ls(now) && rs(now)){  int z = d[rs(now)].rank > d[ls(now)].rank;  rotate(now, z), del(d[now].ch[!z], val);  }  else now = ls(now) ? ls(now) : rs(now);  }  else if(d[now].val < val)del(rs(now), val);  else del(ls(now), val);  if(now)pushup(now);  }  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/860980.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最早发明的自平衡二叉树:AVL

前言 更好的阅读体验 默认读者会基本的 BST 操作。 节点定义 平衡因子:BF(BalanceFactor),左子树高 \(-\) 右子树高。 平衡树是让树的形态尽可能像完全二叉树,而不是链。 在 AVL 中,我们认为 \(\left|\text{BF}\right|\le 1\),也就是 BF 为 \(0,1,-1\) 时的子树是平衡的,…

[COCI2015-2016#2] DRZAVA

思路 先把赛时想法搬一部分过来转化题意, 对于 \(n\) 个带权 \(k\) 的点, 任意两点 \(i, j\) 之间有双向连边, 其边权为 \(w_{i, j} = d_{i, j}\) , 求一最小阈值 \(C\) , 满足对于所有 \(w \leq C\) 的边连接后, 存在一个连通块 \(G\), 使得 \[\sum_{i = 1}^{\lvert G \rvert}…

The End

一、学期回顾 1.1 回顾你对于软件工程课程的想象 根据你对课程目标和期待,回顾目前的所学所练所得,在哪些方面达到了你的期待和目标,哪些方面还存在哪些不足,为什么? 达成的目标与期待理论与实践结合: 课程的最大目标之一是将软件工程的理论知识应用到实践中。在这一点上…

关于本站

我是 fush,一个很菜的 oier。 这里,我只想分享一些自己在学习记录。 由于本人较菜,有哪里写的不严谨的地方欢迎指出。 除了下面几个账号(本人的),如果要转载请写明出处,谢谢。 洛谷

从 Leafy-Tree 到 WBLT

更好的阅读体验。 UPD:2024/12/04 添加序列操作 UPD:2024/12/10 添加可持久化 前言 前面说过 FHQ-treap 的缺点在于常数。 这次篇文章要讲解 WBLT,码量与 FHQ-treap 差的不多,结构与线段树类似。 也可以分裂合并(不推荐),可持久化,但常数远小于 FHQ-treap。 美中不足的…

快消零售业的创新之路:智能AI助力员工培训SOP高效构建

在快速消费品零售行业,员工培训是提升服务质量、增强竞争力的重要手段。然而,传统员工培训方式往往存在培训周期长、效果难以评估等问题,难以满足快消零售行业对于高效、精准培训的需求。随着人工智能技术的不断发展,智能AI在员工培训中的应用逐渐受到重视,特别是在构建员…

django rest framework 视图类关系图

纸上得来终觉浅,绝知此事要躬行

挖掘内部知识库在员工培训与发展中的巨大潜力

在当今快速变化的商业环境中,企业的核心竞争力越来越依赖于其员工的技能水平和持续学习能力。员工培训与发展不再是简单的技能传授,而是需要构建一个能够激发潜能、促进知识共享与创新的智慧学习生态。内部知识库,作为这一生态的核心组成部分,其潜力在员工培训与发展中日益…

数学专题 2024.12

数学专题 2024.12 Luogu 3175 按位或 刚开始你有一个数字 \(0\),每一秒钟你会随机选择一个 \([0,2^n-1]\) 的数字,与你手上的数字进行或(C++,C 的 |,pascal 的 or)操作。选择数字 \(i\) 的概率是 \(p_i\)。保证 \(0\leq p_i \leq 1\),\(\sum p_i=1\) 。问期望多少秒后,你…

AGENT AI-surveying the horizons of multimodal interaction

(转自https://www.cnblogs.com/hifrank/p/18416222) 标题:AGENT AI: surveying the horizons of multimodal interaction作者:Zane Durante, Qiuyuan Huang, Naoki Wake, Ran Gong, Jae Sung Park, Bidipta Sarkar, Rohan Taori, Yusuke Noda, Demetri Terzopoulos, Yejin …

一些数学证明

货舱选址问题 结论:发现对于一些数轴上的点,想要让其和某一点的距离之和最小,要取中位数(偶数/奇数都可以取n/2计算)

【PHP应用】使用http通道连接数据库

#Navicat #PHP #MySQL 办公网和内网的网络并不是完全互通的,內网只支持特定端口范围供办公网访问,因此如果数据库的端口不在这个端口范围内,那么就无法在mac上使用mysql客户端连接内网的数据库。 在开发过程中,有很多要连接的数据库,有的端口在特定端口范围,有的不在,平…