平衡二叉树(AVL)

代码参考:http://blog.youkuaiyun.com/wypblog/article/details/8119616

平衡二叉树(Balanced binary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskii and Landis)1962年首先提出的,所以又称为AVL树。

定义:平衡二叉树或为空树,或为如下性质的二叉排序树:

  1)左右子树深度之差的绝对值不超过1;

  2)左右子树仍然为平衡二叉树.

      平衡因子BF=左子树深度-右子树深度.

平衡二叉树每个结点的平衡因子只能是10-1。若其绝对值超过1,则该二叉排序树就是不平衡的。

如图所示为平衡树和非平衡树示意图:

二、平衡二叉树算法思想

若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。首先要找出插入新结点后失去平衡的最小子树根结点的指针。然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。

        失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。假设用A表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。

 1LL型平衡旋转法

由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行一次顺时针旋转操作。即将A的左孩子B右上旋转代替A作为根结点,A右下旋转成为B的右子树的根结点。而原来B的右子树则变成A的左子树。

2RR型平衡旋转法

由于在A的右孩子C的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行一次逆时针旋转操作。即将A的右孩子C左上旋转代替A作为根结点,A左下旋转成为C的左子树的根结点。而原来C的左子树则变成A的右子树。

3LR型平衡旋转法

由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将A结点的左孩子B的右子树的根结点D左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。即先使之成为LL型,再按LL型处理

      如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为LL型,再按LL型处理成平衡型。

4RL型平衡旋转法 

由于在A的右孩子C的左子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行两次旋转操作(先顺时针,后逆时针),即先将A结点的右孩子C的左子树的根结点D右上旋转提升到C结点的位置,然后再把该D结点向左上旋转提升到A结点的位置。即先使之成为RR型,再按RR型处理。

 如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为RR型,再按RR型处理成平衡型。

平衡化靠的是旋转。参与旋转的是3个节点(其中一个可能是外部节点NULL),旋转就是把这3个节点转个位置。注意的是,左旋的时候p->right一定不为空,右旋的时候p->left一定不为空,这是显而易见的。

如果从空树开始建立,并时刻保持平衡,那么不平衡只会发生在插入删除操作上,而不平衡的标志就是出现bf == 2或者 bf == -2的节点。

#include <stdio.h>
#include <stdlib.h>
/************************************************************************/
/*                    平衡二叉树---AVL                                  */
/************************************************************************/
#define LH +1
#define EH  0
#define RH -1
typedef int ElemType;
typedef struct BSTNode{
	ElemType data;
	int bf;//balance flag
	struct BSTNode *lchild,*rchild;
}*PBSTree;

void R_Rotate(PBSTree* p)
{
	PBSTree lc = (*p)->lchild;
	(*p)->lchild = lc->rchild;
	lc->rchild = *p;
	*p = lc;
}

void L_Rotate(PBSTree* p)
{
	PBSTree rc = (*p)->rchild;
	(*p)->rchild = rc->lchild;
	rc->lchild = *p;
	*p = rc;
}

void LeftBalance(PBSTree* T)
{
	PBSTree lc,rd;
	lc = (*T)->lchild;
	switch (lc->bf)
	{
	case LH:
		(*T)->bf = lc->bf = EH;
		R_Rotate(T);
		break;
	case RH:
		rd = lc->rchild;
		switch(rd->bf)
		{
		case LH:
			(*T)->bf = RH;
			lc->bf = EH;
			break;
		case EH:
			(*T)->bf = lc->bf = EH;
			break;
		case RH:
			(*T)->bf = EH;
			lc->bf = LH;
			break;
		}
		rd->bf = EH;
		L_Rotate(&(*T)->lchild);
		R_Rotate(T);
		break;
	}
}

void RightBalance(PBSTree* T)
{
	PBSTree lc,rd;
	lc= (*T)->rchild;
	switch (lc->bf)
	{
	case RH:
		(*T)->bf = lc->bf = EH;
		L_Rotate(T);
		break;
	case LH:
		rd = lc->lchild;
		switch(rd->bf)
		{
		case LH:
			(*T)->bf = EH;
			lc->bf = RH;
			break;
		case EH:
			(*T)->bf = lc->bf = EH;
			break;
		case RH:
			(*T)->bf = EH;
			lc->bf = LH;
			break;
		}
		rd->bf = EH;
		R_Rotate(&(*T)->rchild);
		L_Rotate(T);
		break;
	}
}

int InsertAVL(PBSTree* T,ElemType e,bool* taller)
{
	if ((*T)==NULL)
	{
		(*T)=(PBSTree)malloc(sizeof(BSTNode));
		(*T)->bf = EH;
		(*T)->data = e;
		(*T)->lchild = NULL;
		(*T)->rchild = NULL;
	}
	else if (e == (*T)->data)
	{
		*taller = false;
		return 0;
	}
	else if (e < (*T)->data)
	{
		if(!InsertAVL(&(*T)->lchild,e,taller))
			return 0;
		if(*taller)
		{
			switch ((*T)->bf)
			{
			case LH:
				LeftBalance(T);
				*taller = false;
				break;
			case  EH:
				(*T)->bf = LH;
				*taller = true;
				break;
			case RH:
				(*T)->bf = EH;
				*taller = false;
				break;
			}
		}
	}
	else
	{
		if(!InsertAVL(&(*T)->rchild,e,taller))
			return 0;
		if (*taller)
		{
			switch ((*T)->bf)
			{
			case LH:
				(*T)->bf = EH;
				*taller = false;
				break;
			case EH:
				(*T)->bf = RH;
				*taller = true;
				break;
			case  RH:
				RightBalance(T);
				*taller = false;
				break;
			}
		}
	}
	return 1;
}

bool FindNode(PBSTree root,ElemType e,PBSTree* pos)
{
	PBSTree pt = root;
	(*pos) = NULL;
	while(pt)
	{
		if (pt->data == e)
		{
			//找到节点,pos指向该节点并返回true
			(*pos) = pt;
			return true;
		}
		else if (pt->data>e)
		{
			pt = pt->lchild;
		}
		else
			pt = pt->rchild;
	}
	return false;
}
void InorderTra(PBSTree root)
{
	if(root->lchild)
		InorderTra(root->lchild);
	printf("%d ",root->data);
	if(root->rchild)
		InorderTra(root->rchild);
}

int main()
{
	int i,nArr[] = {1,23,45,34,98,9,4,35,23};
	PBSTree root=NULL,pos;
	bool taller;
	for (i=0;i<9;i++)
	{
		InsertAVL(&root,nArr[i],&taller);
	}
	InorderTra(root);
	if(FindNode(root,103,&pos))
		printf("\n%d\n",pos->data);
	else
		printf("\nNot find this Node\n");
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值