Treap

本文详细介绍了Treap数据结构的性质、复杂度、旋转操作,并提供了基本代码实现,包括节点的添加、删除和旋转。此外,还讨论了Treap在解决实际问题中的应用,如查找前驱和后继节点,以及在洛谷上的例题解析和练习题目推荐。
摘要由CSDN通过智能技术生成

Treap思路

Treap性质

建一棵二叉搜索树,每个节点除了有一个数值外,还需要赋予一个随机值 r d rd rd。这一棵二叉搜索树同时满足两个条件:

  • 满足二叉搜索树的基本性质:一个节点的左儿子的值小于他,一个节点的右儿子的值大于它。
  • 赋予的随机值满足小顶堆的基本性质。

Treap复杂度

事实上,Treap至今还没有得到严谨的证明时间复杂度为 Θ ( n log ⁡ n ) \Theta(n\log n) Θ(nlogn),但是只要这个随机生成的序列不是基本严格递增的,那么这一棵Treap就一定不会退化为 Θ ( n 2 ) \Theta(n^2) Θ(n2),接近于 Θ ( n log ⁡ n ) \Theta(n\log n) Θ(nlogn)。虽然Treap的时间复杂度没有Splay树等稳定,但一般也不会卡点测试你的代码,srand成系统时间即可。

Treap旋转

改变Treap的形态但是不改变Treap性质的过程称之为旋转。Treap的旋转定义与Splay树有所不同。Treap中,左旋指把根节点放到左边,右旋指把根节点放到右边,可形象理解为左旋即为把整棵树向左边掰一个节点,右旋即为把整棵树向右边掰一个节点。

左旋右旋示意图
思路基本介绍完毕,接下来讲代码。

Treap基本代码

所需变量

开始前,需要定义两个基本变量: r t , t o t rt,tot rt,tot,其中, r t rt rt表示该Treap的根节点是谁,而 t o t tot tot表示一共有多少个节点。

对于树中的每一个节点,需要有这样几个变量: l , r , s z , c n t , k e y , r d l,r,sz,cnt,key,rd l,r,sz,cnt,key,rd l , r l,r l,r分别表示这个节点的左儿子与右儿子分别是谁, s z sz sz表示以这个点为根节点的二叉树的所有节点数量是多少, c n t cnt cnt表示与该节点相等的数有多少个(如果值相等,那么直接将该节点的 c n t cnt cnt++,但是不加入新的节点), k e y key key表示数值, r d rd rd表示赋予该节点的随机数。

c o d e : \tt{code:} code:

struct node{
   
	int l,r,sz,cnt,key,rd;
}tr[100010];
int rt=0,tot=0;

加入节点

每次新加入节点时,需要通过点权( k e y key key值)大小找到该数值在Treap中的正确位置,将这个节点的 l , r l,r l,r都设为 0 0 0,将 s z , c n t sz,cnt sz,cnt都设为 1 1 1(都只有该节点自己), k e y key key值即为数值, r d rd rd值即为随机生成值。

在加入节点完毕后,回溯的时候需要将整一棵树左旋或右旋,保证平衡性。

c o d e : \tt{code:} code:

void insert(int &nd,int x){
   //插入
	if(nd==0){
   
		nd=++tot;
		tr[nd].key=x;
		tr[nd].rd=rand()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值