手写一个节点大小平衡树(SBT)模板,留着用

Posted yxysuanfa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写一个节点大小平衡树(SBT)模板,留着用相关的知识,希望对你有一定的参考价值。

看了一下午,感觉有了些了解。应该没有错,有错希望斧正,感谢

#include<stdio.h>
#include<string.h>
struct s
{
	int key,left,right,size;
}tree[10010];
int top;
void left_rot(int &x)// 左旋
{
	int y=tree[x].right;
	tree[x].right=tree[y].left;
	tree[y].left=x;
	tree[y].size=tree[x].size;
	tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
	x=y;
}
void right_rot(int &x)//右旋
{
	int y=tree[x].left;
	tree[x].left=tree[y].right;
	tree[y].right=x;
	tree[y].size=tree[x].size;
	tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
	x=y;
}
void maintain(int &x,bool flag)//维护SBT状态
{
	if(flag==false)//左边
	{
		if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)//左孩子的左孩子大于右孩子
			right_rot(x);
		else
			if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)//左孩子的右孩子大于右孩子
			{
				left_rot(tree[x].left);
				right_rot(x);	
			}
			else
				return;
	}
	else//右边
	{
		if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size)//右孩子的右孩子大于左孩子
			left_rot(x);
		else
			if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)//右孩子的左孩子大于左孩子
			{
				right_rot(tree[x].right);
				left_rot(x);
			}
			else
				return;
	}
	maintain(tree[x].left,false);
	maintain(tree[x].right,true);
	maintain(x,true);
	maintain(x,false);
}
void insert(int &x,int key)//插入
{
	if(x==0)
	{
		x=++top;
		tree[x].left=0;
		tree[x].right=0;
		tree[x].size=1;
		tree[x].key=key;
	}
	else
	{
		tree[x].size++;
		if(key<tree[x].key)
			insert(tree[x].left,key);
		else
			insert(tree[x].right,key);//同样元素可插右子树
		maintain(x,key>=tree[x].key);
	}
}
int remove(int &x,int key)//利用后继删除
{
	tree[x].size--;
	if(key>tree[x].key)
		remove(tree[x].right,key);
	else
		if(key<tree[x].key)
			remove(tree[x].left,key);
		else
			if(tree[x].left!=0&&tree[x].right==0)//有左子树,无右子树
			{
				int temp=x;
				x=tree[x].left;
				return temp;
			}
			else
				if(!tree[x].left&&tree[x].right!=0)//有右子树,无左子树
				{
					int temp=x;
					x=tree[x].right;
					return temp;
				}
				else
					if(!tree[x].left&&!tree[x].right)//无左右子树
					{
						int temp=x;
						x=0;
						return temp;
					}
					else//左右子树都有
					{
						int temp=tree[x].right;
						while(tree[temp].left)
							temp=tree[temp].left;
						tree[x].key=tree[temp].key;
						remove(tree[x].right,tree[temp].key);
					}
}
int getmin(int x)//求最小值
{
	while(tree[x].left)
		x=tree[x].left;
	return tree[x].key;
}
int getmax(int x)//求最大值
{
	while(tree[x].right)
		x=tree[x].right;
	return tree[x].key;
}
int pred(int &x,int y,int key)//前驱,y初始前驱,从0開始, 终于要的是返回值的key值
{
	if(x==0)
		return y;
	if(key>tree[x].key)
		return pred(tree[x].right,x,key);
	else
		return pred(tree[x].left,y,key);
}
int succ(int &x,int y,int key)//后继。同上
{
	if(x==0)
		return y;
	if(key<tree[x].key)
		return succ(tree[x].left,x,key);
	else
		return succ(tree[x].right,y,key);
}
int select(int &x,int k)//选第k小的数
{
	int r=tree[tree[x].left].size+1;
	if(r==k)
		return tree[x].key;
	else
		if(r<k)
			return select(tree[x].right,k-r);
		else
			return select(tree[x].left,k);
}
int rank(int &x,int key)//key排第几
{
	if(key<tree[x].key)
	{
		return rank(tree[x].left,key);
	}
	else
		if(key>tree[x].key)
			return rank(tree[x].right,key)+tree[tree[x].left].size+1;
		else
			return tree[tree[x].left].size+1;
}
void order(int &x)
{
	if(x==0)
		return;
	order(tree[x].left);
	printf("%d\n",tree[x].key);
	order(tree[x].right);
}
int main()
{
	top=0;
}


以上是关于手写一个节点大小平衡树(SBT)模板,留着用的主要内容,如果未能解决你的问题,请参考以下文章

节点大小平衡树的基本操作

平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板超详解

P3369 模板普通平衡树(Treap/SBT)

AC日记——模板普通平衡树(Treap/SBT) 洛谷 P3369

题解 P3369 模板普通平衡树(Treap/SBT)

替罪羊树 ------ luogu P3369 模板普通平衡树(Treap/SBT)