平衡二叉树AVL的基本操作之插入

        平衡二叉树或是一棵空树,或是具有下列性质的二叉排序树:其左子树和右子树都是平衡二叉树,而且左右子树深度之差绝对值不超过1. 由此引出了平衡因子(balance factor)的概念,bf定义为该结点的左子树的深度减去右子树的深度(有些书是右子树深度减去左子树深度,我是按照左子树减去右子树来计算的,下面的代码也是这样定义的),所以平衡二叉树的结点的平衡因子只可能是 -1,0,1 ,某个结点的平衡因子绝对值大于1,该二叉树就不平衡。

        平衡二叉树在出现不平衡状态的时候,要进行平衡旋转处理,有四种平衡旋转处理(单向右旋处理,单向左旋处理,双向旋转(先左后右)处理,双向旋转(先右后左)处理),归根到底是两种(单向左旋处理和单向右旋处理)。

下面是四种旋转的示意图:


图1 LL旋转 和 RR旋转


图2  LR旋转


图3 LR旋转和LL旋转



图4  RL旋转


图5  LR旋转

        这四种旋转可以归纳为两类:LL旋转和LR旋转可以归为左旋转,RR旋转和RL旋转归为右旋转。

类型定义:

typedef struct AVLNode * AVLTree;

typedef struct AVLNode{
	int data;
	short int bf;
	AVLTree lchild,rchild;
}AVLNode;
左旋函数:

void leftRotate(AVLTree *root,bool *unbalanced)
{
	AVLTree child,gchild;//gchild : grand child
	child = (*root)->lchild;
	if (child->bf == 1) {
		/* LL rotation */
		(*root)->lchild = child->rchild;
		child->rchild = *root;
		(*root)->bf = 0;
		(*root) = child;
	}
	else {
		/* LR rotation */
		gchild = child->rchild;
		child->rchild = gchild->lchild;
		gchild->lchild = child;
		(*root)->lchild = gchild->rchild;
		gchild->rchild = *root;
		switch (gchild->bf) {
			case 1:		(*root)->bf = -1;
						child->bf = 0;
						break;
			case 0:		(*root)->bf = child->bf = 0;
		 				break;
		 	case -1:	(*root)->bf = 0;
		 				child->bf = 1;
		}
		*root = gchild;	
		
	}
	(*root)->bf = 0;
	*unbalanced = false;
} 

右旋函数:

void rightRotate(AVLTree *root, bool *unbalanced)
{
	AVLTree child,gchild;/*gchild : grand child*/ 
	child = (*root)->rchild;
	if (child->bf == -1) {
		/* RR rotation */
		(*root)->rchild = child->lchild;
		child->lchild = *root;
		(*root)->bf = 0;
		(*root) = child;
	}
	else {
		/* RL rotation */
		gchild = child->lchild;
		child->lchild = gchild->rchild;
		gchild->rchild = child;
		(*root)->rchild = gchild->lchild;
		gchild->lchild = *root;
		switch (gchild->bf) {
			case -1:	(*root)->bf = 1;
						child->bf = 0;
						break;
			case 0:		(*root)->bf = child->bf = 0;
		 				break;
		 	case 1:		(*root)->bf = 0;
		 				child->bf = -1;
		}
		*root = gchild;	
		
	}
	(*root)->bf = 0;
	*unbalanced = false;
}

AVL树的插入函数:


void AVLInsert(AVLTree *root, int x, bool *unbalanced)
{
	if(*root == NULL){
		/* insert into a null tree */
		*unbalanced = true;
		*root = new AVLNode;
		(*root)->lchild = (*root)->rchild = NULL;
		(*root)->bf = 0;
		(*root)->data = x;
	}
	else if (x < (*root)->data) {
		AVLInsert(&((*root)->lchild),x,unbalanced);
		if (*unbalanced)
		/* left branch has grown higher */
			switch ((*root)->bf) {
				case -1: 	(*root)->bf = 0;
							*unbalanced  = false;
							break;
				case 0: 	(*root)->bf = 1;
							break;
				case 1:		leftRotate(root,unbalanced);
			}
	}
	else if (x > (*root)->data) {
		AVLInsert(&((*root)->rchild), x, unbalanced);
		if (*unbalanced)
		/* right branch has grown higher */
			switch ((*root)->bf){
				case 1: 	(*root)->bf = 0;
							*unbalanced = false;
							break;
				case 0:		(*root)->bf = -1;
							break;
				case -1:	rightRotate(root,unbalanced);
			} 
	}
	else {
		*unbalanced = false;
		cout<<"Node x = "<<x<<" is alreay in the tree."<<endl;
	}
}


测试结果:

从0到9到插入结果

 0
---------------------cut---------------------
   0  
     \
     1
---------------------cut---------------------
   1  
 /   \
 0   2
---------------------cut---------------------
       1      
     /   \    
   0       2  
             \
             3
---------------------cut---------------------
       1      
     /   \    
   0       3  
         /   \
         2   4
---------------------cut---------------------
       3      
     /   \    
   1       4  
 /   \       \
 0   2       5
---------------------cut---------------------
       3      
     /   \    
   1       5  
 /   \   /   \
 0   2   4   6
---------------------cut---------------------
               3              
             /   \            
       1               5      
     /   \           /   \    
   0       2       4       6  
                             \
                             7
---------------------cut---------------------
               3              
             /   \            
       1               5      
     /   \           /   \    
   0       2       4       7  
                         /   \
                         6   8
---------------------cut---------------------
               3              
             /   \            
       1               7      
     /   \           /   \    
   0       2       5       8  
                 /   \       \
                 4   6       9
---------------------cut---------------------

REF:

1,http://blog.csdn.net/jkay_wong/article/details/6676488

2,数据结构(C语言版) Ellis Horowitz



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值