AVL树插入操作InsertAVL的实现

Posted lxy-xf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AVL树插入操作InsertAVL的实现相关的知识,希望对你有一定的参考价值。

AVL树是非常重要的一种数据结构,这里实现了在AVL树中的插入操作,包括插入后整个树的自平衡。

这里有几点值得注意的地方:

1).左旋L_Rotate与右旋R_Rotate操作:

这两个操作传递进来的参数是以TreeNode*&的形式传递进来的,也就是说传递的是指针的引用,效果等价于传递二级指针

如果不加入&,则在函数内部更改的是形参的指向,因为实际上函数调用时,如果不采用引用传递,则会构造一个与原T指向同一个地方的临时变量指针,在X_Rotate的内部也是对这个临时变量进行操作,等到返回后对原来的T一点影响都没有。因此对于指针的操作,如果说需要在某个函数内更改这个指针的指向,则要么传递二级指针,要么传递指针的引用。

2).在LR型或RL型中:

以LR型为例,要根据不平衡点的左子树的根的右孩子rd的bf值来确定T与lc的bf值,其中rd->bf会出现等于0的情况。

这种情况只会出现在rc才是新插入的节点,也就是说lc->right在原来未插入时是NULL,只有在这种情况下才会显现在rc->bf=0,树却增高的情况。

 

一点小小的总结:

AVL树第一次接触感觉很复杂,转来转去,四个形状,其实思考清楚后整个思路还是很简单的:

首先是LL型与RR型:

这两种情况是最简单的,只需要简单的右旋/左旋即可.

以LL型为例子:对T右旋后,实际上就是将T->left->right接到T的left上,并将T->left->right改为接上T。

RR型也是如此。

然后是LR型与RL型:

这两种情况复杂的原因在于,仅仅是右旋/左旋,T的bf仍不会变化。

以LR型为例子:

问题出现在右旋后将T->left->right接到T的left并不会改变T的bf。

但实际上LR型可以看做这样一个过程:先将他转换为LL型。

也就是说,如果把插入节点插入到T->left的左子树上,就转变为第一个问题了。

现在的问题在于怎么把插入在T->left的右子树上的节点看做插在左子树上呢,只要我们对T->left进行一次左旋。

我们现在将T->left看做一个树的根节点,对这个T’进行一次左旋,根据左旋的规则发现原本插在T‘->right上的节点现在被旋转到T‘->right上了,而T->left的位置现在被T‘->left->right所占据,现在的问题变为了LL型,则只要想问题一一样进行一次右旋就可以了。

这也就是LR型的整个过程。

对RL型也是如此。

struct TreeNode

	int val;
	int bf;
	struct TreeNode* left;
	struct TreeNode* right;
;
class Solution

public:
	int InsertAVL(TreeNode*& T,int val,bool& taller)
	
		if(!T)
		
			T=new TreeNode;
			T->bf=0;
			T->left=T->right=NULL;
			T->val=val;
			taller=true;
		
		else
		
			if(val==T->val)
			
				taller=false;
				return 0;
			
			else if(val<T->val)//left
			
				if(!InsertAVL(T->left,val,taller))
					return 0;
				if(taller)
				
					switch(T->bf)
					
					case -1:
						taller=false;T->bf=0;break;
					case 0:
						taller=true;T->bf=1;break;
					case 1:
						LeftBalance(T);taller=false;break;
					
				
			
			else
			
				if(!InsertAVL(T->right,val,taller))
					return 0;
				if(taller)
				
					switch(T->bf)
					
					case 1:
						taller=false;T->bf=0;break;
					case 0:
						taller=true;T->bf=-1;break;
					case -1:
						RightBalance(T);taller=false;break;
					
				
			
		
		return 1;
	
private:
	void R_Rotate(TreeNode*& p)//注意这里是传递的指针的引用,效果等价于传递二级指针
	
		TreeNode* lc=p->left;
		p->left=lc->right;
		lc->right=p;
		p=lc;
	
	void L_Rotate(TreeNode*& p)
	
		TreeNode* rc=p->right;
		p->right=rc->left;
		rc->left=p;
		p=rc;
	
	void LeftBalance(TreeNode*& T)
	
		TreeNode* lc=T->left;
		switch(lc->bf)
		
		case 1:
			T->bf=lc->bf=0;R_Rotate(T);break;
		case -1:
			TreeNode* rd=lc->right;
			switch(rd->bf)
			
			case 1:
				lc->bf=0;T->bf=-1;break;
			case 0://注意这里rd->bf=0.这种情况是rd这个节点就是新插入的节点,它的左右子树都为空,所以rd->bf=0.只有这种情况才会出现rd->bf=0
				lc->bf=T->bf=0;break;
			case -1:
				lc->bf=1;T->bf=0;break;
			
			rd->bf=0;
			L_Rotate(T->left);
			R_Rotate(T);
			break;
		
	
	void RightBalance(TreeNode*& T)
	
		TreeNode* rc=T->right;
		switch(rc->bf)
		
		case -1:
			rc->bf=T->bf=0;break;
		case 1:
			TreeNode* ld=rc->left;
			switch(ld->bf)
			
			case -1:
				rc->bf=0;T->bf=1;break;
			case 0:
				rc->bf=T->bf=0;break;
			case 1:
				rc->bf=-1;T->bf=0;break;
			
			ld->bf=0;
			R_Rotate(T->right);
			L_Rotate(T);
			break;
		
	
;

  

以上是关于AVL树插入操作InsertAVL的实现的主要内容,如果未能解决你的问题,请参考以下文章

AVL树/红黑树介绍及插入操作实现

AVL树/红黑树介绍及插入操作实现

AVL树/红黑树介绍及插入操作实现

探索 AVL 树基础原理

AVL树

AVL树