平衡二叉树(AVL树)

本文介绍了平衡二叉树(AVL树)的基本概念,包括平衡因子和最小不平衡子树的定义。在插入节点可能导致树失衡时,通过四种旋转操作(LL、RR、LR、RL型)来恢复平衡。并提供了处理左平衡的算法代码,详细阐述了平衡二叉树的构建和维护过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平衡二叉树的相关概念概念:

       平衡二叉树是一种二叉排序树,它具有如下性质:

           1、每一个结点的左子树和右子树的深度最多相差1;

           2、每一个结点的左子树和右子树也都是平衡二叉树

       平衡因子(BF,balance factor):

           结点的平衡因子是该结点的左子树的深度与右子树的深度之差,有-1,0,1三种值。


       最小不平衡子树

           距离插入结点最近,且平衡因子的绝对值大于1的结点为根的子树,我们称为最小不平衡子树。

平衡二叉树构建的基本思想:

        在构建二叉排序树的过程中,每当插入一个结点时,首先检查是否因插入而破坏了树的平衡性。若是,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。

对平衡树进行调整归纳的4种情况:

(1)LL型

        在A的左孩子的左子树上插入结点F,使A的平衡因子由1变为2,则进行一次顺时针旋转调整。由于结点A和D发生冲突,将D变为A的左子树,如图:

(2)RR型

       和LL型刚刚相反,如图:

(3)LR型

       在A的左孩子的右子树上插入结点F,使A的平衡因子由1变为2,则先进行一次逆时针旋转,再进行一次顺时针旋转。即先使之成为LL型,再按照LL型处理。如图:

(4)RL型

       和LR型刚刚相反,如图:

算法代码:

处理左平衡代码

#define LH 1
#define EH 0
#define RH -1

typedef struct BiNode 
{
	int data;
	int bf;
	struct BiNode *lchild,*rchild;
}BiNode;

void LL(BiNode * p)
{
	BiNode * L;
	L = p->lchild;
	p->lchild = L->rchild;
	L->rchild = p;
	p = L;
}

void RR(BiNode * p)
{
	BiNode * R;
	R = p->rchild;
	p->rchild = R->lchild;
	R->lchild = p;
	p = R;
}

void LeftBalance(BiNode * p)//处理左边平衡情况
{
	BiNode * L,* Lr;
	L = p->lchild;
	switch(L->bf)
	{
	case LH://新结点插入在p的左孩子的左子树上,要作顺时针旋转,即LL处理
		p->bf = L->bf = EH;
		LL(p);
		break;
	case RH://新结点插入在p的左孩子的右子树上,作LR处理
		Lr = L->rchild;
		switch(Lr->bf)//修改p及其左孩子的bf
		{
		case LH:
			p->bf = RH;
			L->bf = EH;
			break;
		case EH:
			p->bf = L->bf = EH;
			break;
		case RH:
			p->bf = EH;
			L->bf = LH;
			break;
		}
		Lr->bf = EH;
		RR(p->lchild);//逆时针处理
		LL(p);//顺时针处理
	}
}
右平衡与左平衡处理情况相反,代码稍加修改就OK了,这里就不给出了,可以参考以上代码。

再看看平衡二叉树整个处理过程(代码):

//在平衡二叉树T中若不存在和e相同的结点,则插入一个数据元素为e的新结点并返回1,否则返回0。若
//因二叉排序树失去平衡,则作旋转处理,taller反映T长高与否
int InsertAVL(BiNode * T,int e,bool * taller)
{
	if (!T)
	{
		T = (BiNode *)malloc(sizeof(BiNode));
		T->data = e;
		T->lchild = T->rchild = NULL;
		T->bf = EH;
		* taller = TRUE;
	}
	else
	{
		if (e == T->data)//若存在相同元素
		{
			*taller = FALSE;
			return FALSE;
		}
		if (e < T->data)//在T的左子树搜索
		{
			if (!InsertAVL(T->lchild,e,taller))//递归处理
				return FALSE;
			if (*taller)//已插入到T的左子树中且左子树“长高”
			{
				switch(T->bf)//检查T的平衡度
				{
				case LH://原本左子树比右子树高,需作左平衡处理
					LeftBalance(T);
					*taller = FALSE;
					break;
				case EH://原本左右子树等高,现因左子树增高而树增高
					T->bf = LH;
					*taller = TRUE;
					break;
				case RH://原本右子树比左子树高,现左右子树等高
					T->bf = EH;
					*taller = FALSE;
					break;
				}
			}
		}
		else//在T的右子树搜索
		{
			if (!InsertAVL(T->rchild,e,taller))
				return FALSE;
			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 TRUE;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值