大话数据结构AVL树理解

#include<stdio.h>
#include<stdlib.h>

#define LH 1 //左边高
#define EH 0 //等高
#define RH -1 //右边高

//右单旋转
/*
			p
		  /	  \
	     L	    Pr   
	   /  \
	   Ll  Lr		
	   |
	   N
*/
void R_Rotate(BiTree *p)
{
	BiTree L;


	//将根的左子树赋给L
	L = (*p)->lchild;

	//根的左子树要变成L的右子树
	(*p)->lchild = L->rchild;

	//L的右子树挂接P的左子树
	L->rchild = (*p);

	//p指向新的根节点
	*p = L;

}
/*
			   p
			 /	 \
			Pr	  R	   
			    /  \
			   Ll  Lr
				   |
				   N
*/
//向左旋转
void L_Rotate(BiTree *p)
{
	BiTree R;

	//R指向p的右子树
	R = (*p)->rchild;

	(*p)->rchild = R->lchild;

	R->lchild = (*p);

	(*p) = R;
}

void LeftBalance(BiTree *T)
{
	BiTree L, Lr;
	L = (*T)->lchild;
	switch (L->bf)
	{
		//左边高
		case LH:
			(*T)->bf = L->bf = EH;
			//新节点插入在T的左孩子的左子树上,要做单右旋处理
			R_Rotate(T);
			break;

		case RH://新节点插入在T的左孩子的右子树上,要做双旋处理
			/*
			
			    插入后的左子树的bf跟根的bf不同,左子树为负,根为正,要进行双旋,先左旋,后右旋

							 P
						   /  \
						  L	   Pr
						/  \     \
					   Ll   Lr   ...
					       /   \
						  Lr1  Lrr
						   |
						   N

						   Lr
						/	   \
					   L        p
					 /  \     /   \
					Ll	 Lr1 Lrr	Pr
						  |		     \
					      N           ...
					  

			*/
			//Lr指向T的左孩子的右子树根
			Lr = L->rchild;
			switch (Lr->bf)
			{

				//这里对应了三种情况,具体要画出最后的图
				case LH:
					(*T)->bf = RH;
					L->bf = EH;
					break;

				case EH:
					(*T)->bf = L->bf = EH;
					break;
			
				case RH:
					(*T)->bf = EH;
					L->bf = LH;
					break;

			}

			Lr->bf = EH;
			L_Rotate(&(*T)->lchild);//对T的左子树作左旋平衡处理
			R_Rotate(T);//对T作右旋平衡处理
	}
}
void RightBalance(BiTree *T)
{
	BiTree L, Lr;
	L = (*T)->rchild;
	
	switch (L->bf)
	{
		case RH:
			L->bf = (*T)->bf = EH;
			//传二级指针的地址
			L_Rotate(T);
			break;

		case LH:

			Lr = L->lchild;

			switch (Lr->bf)
			{
				case LH:
					(*T)->bf = RH;
					L->bf = EH;
					break;

				case EH:
					(*T)->bf = L->bf = EH;
					break;

				case RH:
					(*T)->bf = LH;
					L->bf = EH;
					break;
			}
			Lr->bf = EH;

			R_Rotate(&(*T)->rchild);

			L_Rotate(T);
	}

}


//插入avl树中
Status InsertAVL(BiTree *T, int e, Status *taller)
{
	if (!*T)
	{
		*T = (BiTree)malloc(sizeof(BiTNode));
		(*T)->data = e;
		(*T)->lchild = (*T)->rchild = NULL;
		(*T)->bf = EH;

		//插入成功后赋值为TRUE
		*taller = TRUE;
	}
	else
	{
		if (e == (*T)->data)
		{
			*taller = FALSE;
			return FALSE;
		}

		//数据比根节点的值小,要插到左子树上
		if (e < (*T)->data)
		{
			if (!InsertAVL(&(*T)->lchild, e, taller))//没有插入
				return FALSE;

			//已经插入
			if (*taller)
			{
				//检查T的平衡度
				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 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;

}

//这里使用的是前序遍历
void TravelTree(BiTree *p)
{
	BiTree T = *p;

	if (T)
	{
		printf("%d",T->data);
		TravelTree(T->lchild);
		TravelTree(T->rchild);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值