学习:treap

背景

由于对于普通的二叉搜索树,

随机数据倒是没有什么

但是构造数据很容易就会其退化为1条链

也就是说从\(O(log_n)\)的优秀复杂度退化到\(O(n)\)

有人想到,可以对深度太深的树进行一次中序遍历

重新来构建这颗树,也就是替罪羊树

但是实在是太暴力,而且不太好写

所以人们想到了另一个方案,treap

原理

treap从字母的构成上很像tree+heap,也就是树+堆

我们对每一个节点设定一个优先值,

同时,对于这个节点的两个儿子

一定会满足左儿子的优先级<当前节点的优先级>右儿子的优先级

也就是我们强行将构造的数据转换成随机的数据,

所以期望的时间复杂度\(O(log_n)\)

操作&代码

旋转

void update(int k)
{
	tre[k].siz=tre[tre[k].chil[0]].siz+tre[tre[k].chil[1]].siz+tre[k].cnt;
}
void rotate(int &x,int d)
{
	int son=tre[x].chil[d];
	tre[x].chil[d]=tre[son].chil[d^1];
	tre[son].chil[d^1]=x;
	update(x);
	x=son;
	update(x);
}

插入

void insert(int &x,int val)
{
	if(!x)
	{
		x=++cnt;
		tre[x].cnt=tre[x].siz=1;
		tre[x].val=val;
		tre[x].rd=rand();
		return;
	}
	else
	{
		tre[x].siz++;
		if(tre[x].val==val)
		{
			tre[x].cnt++;
			return;
		}
		int d=tre[x].val<val;
		insert(tre[x].chil[d],val);
		if(tre[x].rd>tre[tre[x].chil[d]].rd)
			rotate(x,d);
	}
}

cnt与这个数重合的数的个数

删除

void delet(int &x,int val)
{
	if(!x)
		return;
	if(tre[x].val==val)
	{
		if(tre[x].cnt>1)
		{
			tre[x].cnt--;
			tre[x].siz--;
			return;
		}
		int d=tre[tre[x].chil[0]].rd>tre[tre[x].chil[1]].rd;
		if(tre[x].chil[0]==0||tre[x].chil[1]==0)
			x=tre[x].chil[0]+tre[x].chil[1];
		else
		{
			rotate(x,d);
			delet(x,val);
		}
	}
	else
	{
		tre[x].siz--;
		int d=tre[x].val<val;
		delet(tre[x].chil[d],val);
	}
}

查找是队列中的第几小(排名)

int find_rank(int x,int val)
{
	if(!x)
		return 0;
	if(tre[x].val==val)
		return tre[tre[x].chil[0]].siz+1;
	if(tre[x].val>val)
		return find_rank(tre[x].chil[0],val);
	return find_rank(tre[x].chil[1],val)+tre[tre[x].chil[0]].siz+tre[x].cnt;
}

第几小

int find_kth(int root,int k)
{
	int x=root;
	while(1)
	{
		if(k<=tre[tre[x].chil[0]].siz)
			x=tre[x].chil[0];
		else if(k>tre[tre[x].chil[0]].siz+tre[x].cnt)
		{
			k=k-tre[tre[x].chil[0]].siz-tre[x].cnt;
			x=tre[x].chil[1];
		}
		else
			return tre[x].val;
	}
}

前驱&后继

int pre(int x,int val)
{
	if(!x)
		return INT_MIN;
	if(tre[x].val>=val)
		return pre(tre[x].chil[0],val);
	return max(pre(tre[x].chil[1],val),tre[x].val);
}
int suf(int x,int val)
{
	if(!x)
		return INT_MAX;
	if(tre[x].val<=val)
		return suf(tre[x].chil[1],val);
	return min(suf(tre[x].chil[0],val),tre[x].val);
}
posted @ 2019-11-25 20:41  loney_s  阅读(154)  评论(0)    收藏  举报