平衡二叉树 (AVL)

平衡二叉树


平衡二叉树的定义:
1. 左子树的值都小于根

2. 右子树的值都大于根
3. 左子树跟右子树的高度差不超过1
4.左子树、右子树也是平衡二叉树
由此可见,平衡二叉树的定义也是一个递归定义。


 平衡二叉树的调整(分两种情况): 


1)当根节点平衡因子为1时,在左子树添加节点,导致左子树更高,根节点的平衡因子变成2,需要调整
2)当根节点平衡因子为-1,  在右子树上添加节点,导致右子树更高,根节点平衡因子变成-2,需要调整。

Case1:


上图将第一种情况进行了细分,下面针对图1.1,1.2,1.3单独分析

图1.1

在B的左子树上添加节点,导致A的平衡因子变为2,需要调整,进行顺时针右旋调整

在B的右子树添加节点,该情况可以细化为如下三种情况:对于图中标红框,表示在此处添加节点,不影响树的平衡系数。


 

图1.1.1分析

在C节点的左子树加节点的情况分析。对于图1.1.2 C的右子树添加节点以及图1.1.3 C的左子树添加节点,分析与在图1.1.1上一样,所以全部集中到图1.1.1上进行。
在C的左子树添加节点,

在C树的右子树上添加节点

 

 图1.1.1,在C的左子树和右子树上添加节点,处理方法完全一样,先对tree的左孩子节点进行逆时针左旋,再对tree进行顺时针右旋。

 

图1.2

在B的左子树上添加节点,不会影响树的平衡系数。
在B的右子树上添加节点,与图1.1中处理在B的右子树添加节点一致。

图1.3

在B的右子树上添加节点,不会影响树的平衡系数
在B的左子树添加节点,与图1.1中处理在B的左子树中添加节点一致。

 

Case2:


A的平衡系数为-1,在A的右子树中再添加一个节点,导致平衡系数变成-2,需要调整

具体细化成如下三种情况。

先做说明:对B的左子树添加节点,图2.1,2.2处理方法是一样的。
对B的右子树添加节点,图2.1, 2.3处理方法是一致的。
对2.2对B右子树添加节点,与图2.3B左子树添加节点,不会影响树的平衡因子,不做处理。
所以此处只以图2.1为例进行说明。

在B的右子树添加节点:逆时针左旋

 

在B的左子树上添加节点:(由上文分析可知,在C的左子树或者右子树添加节点,处理方法一致,此处不做冗余说明)
先做顺时针右旋,再说逆时针左旋,让树平衡。

由上图分析可知,对于平衡二叉树的调整,总结下来,只有四种情况:

1. tree bf = 1(左子树偏高),在tree->lchild的左子树上添加节点,并且树变高,只需做顺时针右旋操作,即可将树的平衡因子降下来
2. tree bf = 1,在tree->lchild的右子树添加节点,并且树变高,需要做两次变换,先对lchild做逆时针左旋,在对tree做顺时针右旋
 3. tree bf = -1(右子树偏高),在tree->rchild的右子树添加节点,并且树变高,对tree做逆时针左旋

4. tree bf = -1, 在tree->rchild的左子树添加节点,并且树变高,需要做两次变换,先对rchild做顺时针右旋,再对tree做
逆时针左旋

 

具体调整方法如下:
情况一、二处理方法如下:

void leftBalance(avlTreeNode* &tree)
{
    avlTreeNode* lc = tree->left;
	
    switch(lc->bf)
    {
	case LH:	
		tree->bf = EH;
		tree->left->bf = EH;
		LL(tree);
		break;							

	case RH:	
        	avlTreeNode* rc_lc = lc->right;
		tree->bf = EH;
		tree->left->bf = EH;
		tree->left->right->bf = RH;
		RR(lc);
		LL(tree);
		break;
	}
}

 

情况三、四处理方法:

void rightBalance(avlTreeNode* &tree)
{
    avlTreeNode* rc = tree->right;

    switch(rc->bf)
    {
	case LH:
		tree->bf = EH;
		tree->right->bf = RH;
		tree->right->left->bf = EH;
		LL(rc);
		RR(tree);
		break;
	case RH:
		tree->bf = EH;
		tree->right->bf = EH;
		RR(tree);
		break;
	}
}

 

LL:逆时针左旋

void LL(avlTreeNode* &tree)
{
	avlTreeNode* lc = tree->left;
	tree->left = lc->right;
	lc->right = tree;
	tree = lc;
};
RR:顺时针右旋
void RR(avlTreeNode* &tree)
{
	avlTreeNode* rc = tree->right;
	tree->right = rc->left;
	rc->left = tree;
	tree = rc;
};

转载于:https://my.oschina.net/myspaceNUAA/blog/75421

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值