《数据结构》AVL

AVL的定义

  1. 属于二叉查找树,左儿子的值<当前的值<右儿子的值。
  2. 在任意一个节点,左右子树高度差不超过2。

性质

  1. 左子树中任意一节点的值<当前节点的值<右子树中任意一节点的值
  2. 高度为h的AVL树,节点最多有2h-1个。

思想

  1. 通过旋转操作,实现左右子树平衡。

旋转操作(单旋转)

  1. 左旋
node* levo(node *now)/*左旋,rr,r>l*/
    {
		node *tem=now->r;
		now->r=tem->l;
		tem->l=now;
		now->h=Max(height(now->l),height(now->r))+1;
		tem->h=Max(height(tem->l),height(tem->r))+1;
		return tem;
	}
	/*
	      k2
	     /  \
	   k1    z
	  /  \
	 x    y
	 x
	
	 形象一下,假如树是柔软的,现在我们提住k1,并把y接到k2的左下。
	
	      k1
	    /    \
	   x     k2
	   x   /    \
           y    z
 	
 	现在不就平衡了?
	*/
  1. 右旋
node* dext(node *now)/*右旋,ll,l>r*/
	{
		node *tem=now->l;
		now->l=tem->r;
		tem->r=now;
		now->h=Max(height(now->l),height(now->r))+1;
		tem->h=Max(height(tem->l),height(tem->r))+1;
		return tem;
	}
	/*同上*/

但是,我们会发现下面这种情况无法靠单旋转解决

          k2
	     /  \
	   k1    z
	  /  \
	 y    x
	      x
          
    使用单旋转旋后变成
    
    	  k1
	    /    \
	   y     k2
	       /    \
           x    z
           x
	
	依然没有解决问题,为什么呢?

      原来在图1中,单旋转并没有改变x的深度,而是改变了y和k1的深度,这时我们就该用到双旋转了!

  1. 左右旋
node* lext(node *now)/*左右旋,lr,l>r*/
	{
		now->l=levo(now->l);
		return dext(now);
	}
	/*
	是不是很简单?
	其实也不难理解-》就是先通过对左子树进行一次左旋,使高度高的x旋转至左儿子,再通过右旋转使其平衡
	*/
  1. 右左旋
node* devo(node *now)/*右左旋,rl,r>l*/
	{
		now->r=dext(now->r);
		return levo(now);
	}

解决了这些,剩下的便是小菜一碟了

代码如下:
# define Type template<typename T>
Type const T Max(T a,T b){return a>b?a:b;}
Type struct AVL
{
	int tot;
	struct node
	{
		node *l,*r;
		T v;
		int h,s,si;
		node(T tv){l=r=NULL;v=tv;h=s=si=1;}
		node(){l=r=NULL;v=0;h=s=si=1;}
	}*Root,f[1000000];
	AVL(){Root=NULL;tot=0;}
	int height(node *now)
	{
		return now?now->h:0;
	}
	int size(node *now)
	{ 
		return now?now->s:0;
	}
	node* includefindindex(node *now,int k)
	{
		if(k<=size(now->l))return includefindindex(now->l,k);
		if(k>size(now->l)+now->si)return includefindindex(now->r,k-(size(now->l)+now->si));
		return now;
	}
	T operator [](int k)
	{
		return includefindindex(Root,k)->v;
	}
	node* find(T want)
	{
		node *tem=Root;
		while(tem&&tem->v!=want)
			if(tem->v>want)tem=tem->l;
			else tem=tem->r;
		return tem;
	}
	int findrank(T want)
	{
		node *tem=Root;
		int t=0;
		while(tem)
		{
			if(tem->v<want)t+=size(tem->l)+tem->si,tem=tem->r;
			else if(tem->v>want)tem=tem->l;
			else return t+size(tem->l)+1;
		}
		return 1;
	}
	node* levo(node *now)
    {
		node *tem=now->r;
		now->r=tem->l;
		tem->l=now;
		now->h=Max(height(now->l),height(now->r))+1;
		now->s=size(now->l)+size(now->r)+now->si;
		tem->h=Max(height(tem->l),height(tem->r))+1;
		tem->s=size(tem->l)+size(tem->r)+tem->si;
		return tem;
	}
	node* dext(node *now)
	{
		node *tem=now->l;
		now->l=tem->r;
		tem->r=now;
		now->h=Max(height(now->l),height(now->r))+1;
		now->s=size(now->l)+size(now->r)+now->si;
		tem->h=Max(height(tem->l),height(tem->r))+1;
		tem->s=size(tem->l)+size(tem->r)+tem->si;
		return tem;
	}
	node* lext(node *now)
	{
		now->l=levo(now->l);
		return dext(now);
	}
	node* devo(node *now)
	{
		now->r=dext(now->r);
		return levo(now);
	}
	node* balance(node *now)
	{
		if(height(now->l)==height(now->r)+2)
			if(height(now->l->l)>height(now->l->r))now=dext(now);
			else now=lext(now);
		else if(height(now->r)==height(now->l)+2)
			if(height(now->r->r)>height(now->r->l))now=levo(now);
			else now=devo(now);
		return now;
	}
	node* findmin(node *now)
	{
		if(!now)return NULL;
		while(now->l)now=now->l;
		return now;
	}
	node* findmax(node *now)
	{
		if(!now)return NULL;
		while(now->r)now=now->r;
		return now;
	}
	node* includeinsert(node *now,T need)
	{
		if(!now)
		{
			now=f+(tot++);
			now->v=need;
			return now;
		}
		if(need==now->v)++now->si;
		else if(need<now->v)now->l=includeinsert(now->l,need);
		else now->r=includeinsert(now->r,need);
		now->h=Max(height(now->l),height(now->r))+1;
		now->s=size(now->l)+size(now->r)+now->si;
		return balance(now);
	}
	node* includeremove(node *now,T need)
	{
		if(!now)return NULL;
		if(now->v>need)now->l=includeremove(now->l,need);
		else if(now->v<need)now->r=includeremove(now->r,need);
		else if(now->si>1)--now->si;
		else if(now->l&&now->r)
		{
			node* tem=findmin(now->r);
			now->v=tem->v;now->si=tem->si;
			tem->si=1;
			now->r=includeremove(now->r,now->v);
		}
		else if(now->l||now->r)now=now->l?now->l:now->r;
		else return now=NULL;
		now->h=Max(height(now->l),height(now->r))+1;
		now->s=size(now->l)+size(now->r)+now->si;
		return balance(now);
	}
	node* bigger(T need)
	{
		node *tem=Root,*ans=NULL;
		while(tem)
		{
			if(tem->v>=need)
			{
				if(!ans||tem->v<ans->v)ans=tem;
				tem=tem->l;
			}
			else tem=tem->r;
		}
		return ans;
	}
	node* lower(T need)
	{
		node *tem=Root,*ans=NULL;
		while(tem)
		{
			if(tem->v<=need)
			{
				if(!ans||tem->v>ans->v)ans=tem;
				tem=tem->r;
			}
			else tem=tem->l;
		}
		return ans;
	}
	void insert(T need){Root=includeinsert(Root,need);}
	void remove(T need){Root=includeremove(Root,need);}
};
posted @ 2019-02-04 17:32  ファイナル  阅读(266)  评论(0)    收藏  举报