【数据结构】Treap——方便的平衡树

本文介绍了Treap数据结构,一种结合了二叉查找树和堆特性的高效数据结构。Treap能够实现期望logloglog级别的复杂度,并通过随机值维持平衡。文章详细解释了Treap的构建、分裂和合并等基本操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

顾名思义,treap就是tree+Heap,复杂度与Splay的均摊 l o g log log不同,treap是期望 l o g log log,但与Splay比起来,功能都差不多,但代码的长度和调试难度都比Spaly要舒服很多,

简介

treap是一棵二叉查找树,与普通的二叉查找树不同,对于每个节点,它还记录一个随机值 r d rd rd,满足,如果只看 r d rd rd的话,它就是一个堆,
这样,它的期望深度就是 l o g log log的,每次的查询修改直接在上面跑也没问题。

以下为treap的基本操作,各种在这上面扩展出的其他的操作这里就不细讲了

Build

我们可以发现一棵treap同时也是一棵迪笛卡尔树,
那么建树就可以O(n)解决了,用一个栈即可,
(当然你像插入一样做也没问题)

//b[i].rd为位置i的随机值
//merge()为标记的合并,
void build(int q)
{
	if(b[q].l)build(b[q].l);
	if(b[q].r)build(b[q].r);
	merge(q);
}
void build_treap()
{
	int la,w;
	n++;b[n].rd=2e9;
	fo(i,1,n)
	{
		int la=0;
		for(;za[0]&&b[za[za[0]]].rd<b[i].rd;za[0]--)
		{
			la=w=za[za[0]];
			if(za[0]-1)b[w].fa=za[za[0]-1],b[za[za[0]-1]].r=w;
		}
		if(i>n)break;
		b[i].l=la;
		b[la].fa=i;
		za[++za[0]]=i;
	}
	root=n;
	build(root);
}

Split

treap当然离不开Split操作啦,
这个点操作的作用是把treap两棵treap,一半为前si个,另一半就是剩下的,
具体的操作是:判断断开的位置是在左子树还是右子树,再递归求解,
(看标的话理解的会快一点)

//merge()为标记的合并,

typedef pair<int,int> TRP;

TRP split(int q,int si)
{
	if(!si)return TRP(0,q);
	TRP t;
	if(si<=b[b[q].l].si)
	{
		t=split(b[q].l,si);
		b[q].l=t.second;
		t.second=q;
	}else
	{
		t=split(b[q].r,si-1-b[b[q].l].si);
		b[q].r=t.first;
		t.first=q;
	}
	merge(q);
	return t;
}

Merge

合并就简单了,直接把较大的那个放到这个位置即可

//因为merge函数被标记合并占用了,所以只能用另一个词了

int amalgamate(int q,int w)
{
	if(!q||!w)return q+w;
	if(b[q].rd>b[w].rd)
	{
		b[q].r=amalgamate(b[q].r,w);
		merge(q);
		return q;
	}
	b[w].l=amalgamate(q,b[w].l);
	merge(w);
	return w;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值