平衡树——AVL树

二叉搜索树
一种树形结构,满足对于树上的任意一个节点,它的左子树上的任意一个节点的值都不大于这个节点的值,它的右子树上的任意节点的值都不小于这个节点的值。
但是如果是按顺序添加,这个树形结构就会退化为一个链式结构。
为了使得它还是一个树形结构,就需要用到平衡树。
平衡树
一种左右子树平衡的二叉搜索树(左右子树的深度之差小于1)。
AVL树
通过树的旋转来维护平衡树。
树的旋转
1.左旋:原树的根节点的右儿子变成新的根节点,它的右子树依然是它的右子树,它的左子树变成原根节点的右子树,这棵新的以原根节点为根节点的树成为新根节点的左子树。

2.右旋:与左旋正好相反。

1.LL型,即一颗不平衡的二叉搜索树的左子树的深度大于它的右子树的深度,且它左子树的左子树的深度大于它左子树的右子树的深度,操作:对这棵树进行一次右旋。
2.RR型,即一颗不平衡的二叉搜索树的右子树的深度大于它的左子树的深度,且它右子树的右子树的深度大于它右子树的左子树的深度,操作:对这棵树进行一次左旋。
3.LR型,即一颗不平衡的二叉搜索树的左子树的深度大于它的右子树的深度,且它左子树的右子树的深度大于它左子树的左子树的深度,操作:先对这棵树的左子树进行一次左旋,再对这棵树进行一次右旋。
4.RL型,即一颗不平衡的二叉搜索树的右子树的深度大于它的左子树的深度,且它右子树的左子树的深度大于它右子树的右子树的深度,操作:先对这棵树的右子树进行一次右旋,再对这棵树进行一次左旋。
插入
正常二叉搜索树的插入,与一个节点进行比较,小于查左儿子,大于等于查右儿子,直到找到空位插入。回溯时判断一个子树是否平衡,若不平衡则进行树的旋转操作。
删除
删除一共有三种情况:
1.要删除的节点无左子树,也无右子树,直接删除。
2.要删除的节点只有左子树,或只有右子树,直接删除并将左子树(或右子树)变成该节点的子树。
3.要删除的节点既有左子树,又有右子树,找到要删除的节点的前驱节点,把要删除的节点的位置上换成要删除的节点的前驱节点,并把问题换成删除要删除的节点的前驱节点,且此节点一定无右子树。
回溯时也要判断一个子树是否平衡,若不平衡则进行树的旋转操作。
注意:插入时左子树上的任意节点都小于根节点,右子树上的任意节点都大于等于根节点,但在树的旋转操作后,左子树上的节点也可能等于根节点。
代码

#include<iostream>
#include<cmath>
using namespace std;
int n;
struct node{
	int l,r;
	int zhi;
	int deep;
	int zs,ys,sum;
}tree[100010];
int cnt;
int yx(int u){
	int t=tree[u].l;
	tree[u].l=tree[tree[u].l].r;
	tree[u].ys=tree[tree[u].r].sum;
	tree[u].zs=tree[tree[u].l].sum;
	tree[u].sum=tree[u].ys+tree[u].zs+1;
	tree[u].deep=max(tree[tree[u].l].deep,tree[tree[u].r].deep)+1;
	tree[t].r=u;
	u=t;
	return u;
}
int zx(int u){
	int t=tree[u].r;
	tree[u].r=tree[tree[u].r].l;
	tree[u].zs=tree[tree[u].l].sum;
	tree[u].ys=tree[tree[u].r].sum;
	tree[u].sum=tree[u].ys+tree[u].zs+1;
	tree[u].deep=max(tree[tree[u].l].deep,tree[tree[u].r].deep)+1;
	tree[t].l=u;
	u=t;
	return u;
}
int add(int u){
	if(tree[cnt].zhi<tree[u].zhi){
		if(tree[u].l==0){
			tree[u].l=cnt;
			tree[u].deep=max(tree[tree[u].l].deep,tree[tree[u].r].deep)+1;
			tree[u].ys=tree[tree[u].r].sum;
			tree[u].zs=1;
			tree[u].sum=tree[u].zs+tree[u].ys+1;
			return u;
		}
		tree[u].l=add(tree[u].l);
	}
	else{
		if(tree[u].r==0){
			tree[u].r=cnt;
			tree[u].deep=max(tree[tree[u].l].deep,tree[tree[u].r].deep)+1;
			tree[u].zs=tree[tree[u].l].sum;
			tree[u].ys=1;
			tree[u].sum=tree[u].ys+tree[u].zs+1;
			return u;
		}
		tree[u].r=add(tree[u].r);
	}
	if(abs(tree[tree[u].l].deep-tree[tree[u].r].deep)>1){
		if(tree[tree[u].l].deep>tree[tree[u].r].deep){
			if(tree[tree[tree[u].l].l].deep>tree[tree[tree[u].l].r].deep){
				u=yx(u);
			}
			else{
				tree[u].l=zx(tree[u].l);
				u=yx(u);
			}
		}
		else{
			if(tree[tree[tree[u].r].r].deep>tree[tree[tree[u].r].l].deep){
				u=zx(u);
			}
			else{
				tree[u].r=yx(tree[u].r);
				u=zx(u);
			}
		}
	}
	tree[u].deep=max(tree[tree[u].l].deep,tree[tree[u].r].deep)+1;
	tree[u].ys=tree[tree[u].r].sum;
	tree[u].zs=tree[tree[u].l].sum;
	tree[u].sum=tree[u].zs+tree[u].ys+1;
	return u;
}
int gen=0;
int cun=0;
int del(int u,int x){
	if(tree[u].zhi==x){
		if(tree[u].l==0&&tree[u].r==0){
			return 0;
		}
		if(tree[u].l==0){
			return tree[u].r;
		}
		if(tree[u].r==0){
			return tree[u].l;
		}
		cun=u;
	}
	if(tree[u].zhi>=x){
		tree[u].l=del(tree[u].l,x);
		tree[u].ys=tree[tree[u].r].sum;
		tree[u].zs=tree[tree[u].l].sum;
		tree[u].sum=tree[u].zs+tree[u].ys+1;
	}
	else{
		if(tree[u].r==0){
			if(cun!=0){
				tree[cun].zhi=tree[u].zhi;
				return tree[u].l;
			}
		}
		else{
			tree[u].r=del(tree[u].r,x);
			tree[u].zs=tree[tree[u].l].sum;
			tree[u].ys=tree[tree[u].r].sum;
			tree[u].sum=tree[u].zs+tree[u].ys+1;
		}
	}
	if(abs(tree[tree[u].l].deep-tree[tree[u].r].deep)>1){
		if(tree[tree[u].l].deep>tree[tree[u].r].deep){
			if(tree[tree[tree[u].l].l].deep>tree[tree[tree[u].l].r].deep){
				u=yx(u);
			}
			else{
				tree[u].l=zx(tree[u].l);
				u=yx(u);
			}
		}
		else{
			if(tree[tree[tree[u].r].r].deep>tree[tree[tree[u].r].l].deep){
				u=zx(u);
			}
			else{
				tree[u].r=yx(tree[u].r);
				u=zx(u);
			}
		}
	}
	tree[u].deep=max(tree[tree[u].l].deep,tree[tree[u].r].deep)+1;
	tree[u].ys=tree[tree[u].r].sum;
	tree[u].zs=tree[tree[u].l].sum;
	tree[u].sum=tree[u].zs+tree[u].ys+1;
	return u;
}
int pai(int u,int x){
	if(x==0){
		return 0;
	}
	if(tree[u].zhi>=x){
		if(tree[u].l==0){
			return 0;
		}
		return pai(tree[u].l,x);
	}
	if(tree[u].r==0){
		return tree[u].zs+1;
	}
	return tree[u].zs+1+pai(tree[u].r,x);
}
int shu(int u,int x){
	if(x==tree[u].zs+1){
		return tree[u].zhi;
	}
	if(x<=tree[u].zs){
		return shu(tree[u].l,x);
	}
	return shu(tree[u].r,x-tree[u].zs-1);
}
int main(){
	cin>>n;
	while(n--){
		int opt,x;
		cin>>opt>>x;
		if(opt==1){
			cnt++;
			tree[cnt].zhi=x;
			tree[cnt].deep=1;
			tree[cnt].sum=1;
			if(gen!=0){
				gen=add(gen);
			}
			else{
				gen=cnt;
			}
		}
		if(opt==2){
			gen=del(gen,x);
		}
		if(opt==3){
			cout<<pai(gen,x)+1<<endl;
		}
		if(opt==4){
			cout<<shu(gen,x)<<endl;
		}
		if(opt==5){
			cout<<shu(gen,pai(gen,x))<<endl;
		}
		if(opt==6){
			cout<<shu(gen,pai(gen,x+1)+1)<<endl;
		}
	}
	return 0;
}
posted @ 2022-06-13 21:33  zzzzzz2  阅读(78)  评论(0编辑  收藏  举报