基于C语言的平衡二叉树操作(包含完整代码)

平衡二叉树的定义:

 为避免树的高度增长过快,降低二叉排序树的性能,规定在插入和删除二叉树结点时,要保证任意结点的左、右子树高度差的绝对值不超过1,将这样的二义树称为平衡二叉树AVL (Balanced Binary Tree),简称平衡树。

平衡二叉树的插入:

(1) LL平衡旋转(右单旋)

由于在结点A的左孩子(L的在子树(L上插入了新结点,A的平衡因子由1增至2,导致以A为根的子树大去平衡,需要一次向右的旋转操作。将A的左孩子B向右上旋转代替A成为根结点,将A结点向右下旋转成为B的右子树的根结点,而B的原右子树则作为A结点的左子树。
如图7.11所示,结点旁的数值代表结点的平衡因子,而用方块表示相应结点的子树,下方数值代表该子树的高度。 

 

(2) RR平衡旋转(左单旋转)

由于在结点A的右孩子(R)的右子树(R)上插入了新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要一次向左的旋转操作。将A的右孩子B向左上旋转代替A成为根结点,将A结点向左下旋转成为B的左子树的根结点,而B的原左子树则作为A结点的右子树.

 

(3) LR平衡旋转(先左后右旋转)

由于在A 的左孩子(L)的右子树(R)上插入新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先左旋转后右旋转。先将A结点的左孩子B的右子树的根结点C向左上旋转提升到B结点的位置,然后把该C结点向右上旋转提升到A结点的位置.

 

 (4)RL平衡旋转(先右后左双旋转)

 由于在A的右孩子(R)的左子树(L)上插入新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先右旋转后左旋转。先将A结点的右孩子B的左子树的根结点C向右上旋转提升到B结点的位置,然后把该C结点向左上旋转提升到A结点的位置.

  

 1.定义结构体

typedef struct TreeNode
{
	int data;//定义数据域 
	int height;//定义高度 
	struct TreeNode *lchild;//左孩子 
	struct TreeNode *rchild;//右孩子 
}TreeNode;

 2.获取结点高度

int getHeight(TreeNode *node)
{
	return node ? node->height : 0;//判断node是否为空,为空返回0,不为空返回高度 
}

 3.取最大值

int max(int a,int b)
{
	return a > b ? a : b;
}

 4.RR平衡旋转(向左旋转一次)

void rrRotation(TreeNode *node,TreeNode **root)
{/*参数一node:代表该结点
参数二root:代表父结点结点*/
	TreeNode *temp = node->rchild;//右孩子保存给中间指针 
	node->rchild = temp->lchild;//node的左孩子赋值给node的右孩子 
	temp->lchild = node;//node代替node的左孩子 
	node->height = max(getHeight(node->lchild),getHeight(node->rchild))+1;//最大值加一 
	temp->height = max(getHeight(temp->lchild),getHeight(temp->rchild))+1;
	*root = temp;
}

5.LL平衡旋转(向右旋转一次)

void llRotation(TreeNode *node,TreeNode **root)
{/*参数一node:代表该结点
参数二root:代表父结点结点*/
	TreeNode *temp = node->lchild;
	node->lchild = temp->rchild;
	temp->rchild = node;
	node->height = max(getHeight(node->lchild),getHeight(node->rchild))+1;
	temp->height = max(getHeight(temp->lchild),getHeight(temp->rchild))+1;
	*root = temp;
}

 6.建立平衡二叉树

void avlInsert(TreeNode **T,int data)
{/*第一个参数**T:双重解引用,用于更改T中的值
第二个参数data:用于传递元素并比较大小*/
	if(*T==NULL)//首先判断该结点是否为空,是空结点则新建结点并初始化
	{
		*T = (TreeNode*)malloc(sizeof(TreeNode));//申请内存空间 
		(*T)->data = data;//写入数据
		(*T)->height = 0;//高度初始化为0 
		(*T)->lchild = NULL;//左孩子初始为空
		(*T)->rchild = NULL;//右孩子初始为空 
	}
	else if(data<(*T)->data)//data小于当前结点值 
	{
		avlInsert(&(*T)->lchild,data);//要插入的元素比结点内的元素小,则往左子树走
		//拿到当前左右子树的高度 
		int lHeight = getHeight((*T)->lchild);
		int rHeight = getHeight((*T)->rchild);
		if(lHeight-rHeight==2)//判断二叉树是否失衡 
		{//判断高度差 
			if(data<(*T)->lchild->data)//要插入的元素小于当前结点左孩子的元素 
			{//LL型  
				llRotation(*T,T);//右旋一次	
			}
			else
			{//LR型 
				rrRotation((*T)->lchild,&(*T)->lchild);//先左旋 
				llRotation(*T,T);//后右旋 
			}			
		}
	}
	else if(data>(*T)->data)//data大于当前结点值 
	{
		avlInsert(&((*T)->rchild),data);//要插入的元素比结点内的元素大,则往右子树走
		//拿到当前左右子树的高度 		
		int lHeight = getHeight((*T)->lchild);
		int rHeight = getHeight((*T)->rchild);
		if(rHeight-lHeight==2)//判断二叉树是否失衡 
		{//判断高度差 
			if (data>(*T)->rchild->data)
			{//RR型 
				rrRotation(*T,T);//左旋一次 
			}
			else
			{//RL型 
				llRotation((*T)->rchild,&(*T)->rchild);//先右旋 
				rrRotation(*T,T);//后左旋 
			} 
		}
	}
	(*T)->height = max(getHeight((*T)->lchild),getHeight((*T)->rchild))+1;
}

7.前序遍历(根左右)

void preOrder(TreeNode *T)
{
	if(T)
	{
		printf("%d ",T->data);//输出根结点
		preOrder(T->lchild);//递归遍历左子树
		preOrder(T->rchild);//递归遍历右子树
	}
}

8.主函数

int main()
{
	TreeNode *T = NULL;//初始树根结点 
	int nums[5] = {1,2,3,4,5};
	int i;
	for(i=0;i<5;i++)
		avlInsert(&T,nums[i]);//构造平衡二叉树 
	preOrder(T);
	printf("\n");
	return 0;
}

 完整代码:

#include <stdio.h>
#include <stdlib.h>
/*定义结构体*/
typedef struct TreeNode
{
	int data;//定义数据域 
	int height;//定义高度 
	struct TreeNode *lchild;//左孩子 
	struct TreeNode *rchild;//右孩子 
}TreeNode;
/*获取结点高度*/
int getHeight(TreeNode *node)
{
	return node ? node->height : 0;//判断node是否为空,为空返回0,不为空返回高度 
}
/*取最大值*/
int max(int a,int b)
{
	return a > b ? a : b;
}
/*RR平衡旋转(向左旋转一次)*/
void rrRotation(TreeNode *node,TreeNode **root)
{/*参数一node:代表该结点
参数二root:代表父结点结点*/
	TreeNode *temp = node->rchild;//右孩子保存给中间指针 
	node->rchild = temp->lchild;//node的左孩子赋值给node的右孩子 
	temp->lchild = node;//node代替node的左孩子 
	node->height = max(getHeight(node->lchild),getHeight(node->rchild))+1;//最大值加一 
	temp->height = max(getHeight(temp->lchild),getHeight(temp->rchild))+1;
	*root = temp;
}
/*LL平衡旋转(向右旋转一次)*/
void llRotation(TreeNode *node,TreeNode **root)
{/*参数一node:代表该结点
参数二root:代表父结点结点*/
	TreeNode *temp = node->lchild;
	node->lchild = temp->rchild;
	temp->rchild = node;
	node->height = max(getHeight(node->lchild),getHeight(node->rchild))+1;
	temp->height = max(getHeight(temp->lchild),getHeight(temp->rchild))+1;
	*root = temp;
}
/*建立平衡二叉树*/
void avlInsert(TreeNode **T,int data)
{/*第一个参数**T:双重解引用,用于更改T中的值
第二个参数data:用于传递元素并比较大小*/
	if(*T==NULL)//首先判断该结点是否为空,是空结点则新建结点并初始化
	{
		*T = (TreeNode*)malloc(sizeof(TreeNode));//申请内存空间 
		(*T)->data = data;//写入数据
		(*T)->height = 0;//高度初始化为0 
		(*T)->lchild = NULL;//左孩子初始为空
		(*T)->rchild = NULL;//右孩子初始为空 
	}
	else if(data<(*T)->data)//data小于当前结点值 
	{
		avlInsert(&(*T)->lchild,data);//要插入的元素比结点内的元素小,则往左子树走
		//拿到当前左右子树的高度 
		int lHeight = getHeight((*T)->lchild);
		int rHeight = getHeight((*T)->rchild);
		if(lHeight-rHeight==2)//判断二叉树是否失衡 
		{//判断高度差 
			if(data<(*T)->lchild->data)//要插入的元素小于当前结点左孩子的元素 
			{//LL型  
				llRotation(*T,T);//右旋一次	
			}
			else
			{//LR型 
				rrRotation((*T)->lchild,&(*T)->lchild);//先左旋 
				llRotation(*T,T);//后右旋 
			}			
		}
	}
	else if(data>(*T)->data)//data大于当前结点值 
	{
		avlInsert(&((*T)->rchild),data);//要插入的元素比结点内的元素大,则往右子树走
		//拿到当前左右子树的高度 		
		int lHeight = getHeight((*T)->lchild);
		int rHeight = getHeight((*T)->rchild);
		if(rHeight-lHeight==2)//判断二叉树是否失衡 
		{//判断高度差 
			if (data>(*T)->rchild->data)
			{//RR型 
				rrRotation(*T,T);//左旋一次 
			}
			else
			{//RL型 
				llRotation((*T)->rchild,&(*T)->rchild);//先右旋 
				rrRotation(*T,T);//后左旋 
			} 
		}
	}
	(*T)->height = max(getHeight((*T)->lchild),getHeight((*T)->rchild))+1;
}

/*前序遍历(根左右)*/
void preOrder(TreeNode *T)
{
	if(T)
	{
		printf("%d ",T->data);//输出根结点
		preOrder(T->lchild);//递归遍历左子树
		preOrder(T->rchild);//递归遍历右子树
	}
}
int main()
{
	TreeNode *T = NULL;//初始树根结点 
	int nums[5] = {1,2,3,4,5};
	int i;
	for(i=0;i<5;i++)
		avlInsert(&T,nums[i]);//构造平衡二叉树 
	preOrder(T);
	printf("\n");
	return 0;
}

 运行结果:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值