平衡二叉树(AVL)插入与删除

参考大佬:https://blog.csdn.net/m0_37914588/article/details/103754959

单旋与双旋解释

在这里插入图片描述
在这里插入图片描述

结构定义

typedef struct AVLTNode{
	int Data;
	AVLTNode *Left;
	AVLTNode *Right;
	int Height;	//树高
} * AVLTree;

得树高与找最值

/*获得树高*/
int GetHeight(AVLTree AVL)
{
	if (!AVL)
		return 0;
	else
		return AVL->Height;
}
AVLTree FindMin(AVLTree AVL)
{
	if(AVL)
		while(AVL->Left)
			AVL = AVL->Left;
	return AVL;
}
AVLTree FindMax(AVLTree AVL)
{
	if(!AVL)
		return NULL;
	else if(AVL->Right)	//向右递归
		return FindMax(AVL->Right);
	else
		return AVL;
}

单旋与双旋

/*LL左单旋算法*/
AVLTree SingleLeftRotation(AVLTree A)	//能进入这一步A必须有一个左子结点B
{
	AVLTree B = A->Left;
	A->Left = B->Right;		//第1步
	B->Right = A;			//第2步
	/*当已经完成旋转后, 调整树高*/
	A->Height = max(A->Left->Height, A->Right->Height) + 1;	//注意从下往上调整
	B->Height = max(B->Left->Height, A->Height) + 1;

	return B;	//返回树的根结点地址
}
/*RR右单旋算法, 与LL算法一样*/
AVLTree SingleRightRotation(AVLTree A)
{
	AVLTree B = A->Right;
	A->Right = B->Left;
	B->Left = A;

	A->Height = max(A->Left->Height, A->Right->Height) + 1;
	B->Height = max(A->Height, B->Right->Height) + 1;

	return B;
}
/*左-右双旋算法*/
AVLTree DoubleLeftRightRotation(AVLTree A)	//A必须有1个左子结点B, B必须有1个右子结点C
{
	/*将B与C作右单旋, C被返回*/
	A->Left = SingleRightRotation(A->Left);
	/*将A与C作左单旋, C被返回*/
	return SingleLeftRotation(A);
}
/*右-左单旋算法*/
AVLTree DoubleRightLeftRotation(AVLTree A)
{
	A->Right = SingleLeftRotation(A->Right);
	return SingleRightRotation(A);
}

插入算法

/*AVL树的插入*/
AVLTree Insert(AVLTree AVL, int x)	//将x插入AVL树中, 并返回调整后的AVL树
{	/*递归算法*/
	if(!AVL)	//AVL是空树或递归到空结点时, 准备插入x, 作为新的叶结点
	{
		AVL = new AVLTNode();
		AVL->Data = x;
		AVL->Height = 1;
	}
	else if(x < AVL->Data)	//Find要插入的位置
	{
		AVL->Left = Insert(AVL->Left, x);	//递归的Find
		/*完成元素插入后, 判断是否要左旋*/
		if(GetHeight(AVL->Left) - GetHeight(AVL->Right) == 2)
			if(x < AVL->Left->Data)	//插入位置在当前AVL根的左左
				AVL = SingleLeftRotation(AVL);
			else
				AVL = DoubleLeftRightRotation(AVL);
	}
	else if(x > AVL->Data)
	{
		AVL->Right = Insert(AVL->Right, x);
		if(GetHeight(AVL->Right) - GetHeight(AVL->Left) == 2)	//此时右子树插入后高度可能 + 1
			if(x > AVL->Right->Data)
				AVL = SingleRightRotation(AVL);
			else
				AVL = DoubleRightLeftRotation(AVL);
	}
	//else	树中已经有x, 什么也不做

	/*完成上述插入并调整后, 更新树高*/
	AVL->Height = max(GetHeight(AVL->Left), GetHeight(AVL->Right)) + 1;
	return AVL;
}

删除算法

/*AVL树的删除*/
AVLTree Delete(AVLTree AVL, int x)
{
	AVLTree Tmp;
	if(!AVL)
		cout << "No" << endl;
	else
	{
		if(x < AVL->Data)
		{
			AVL->Left = Delete(AVL->Left, x);
			if(GetHeight(AVL->Right) - GetHeight(AVL->Left) == 2)	//即删除左边的可能会导致左边高减少
				if (GetHeight(AVL->Right->Right) >= GetHeight(AVL->Right->Left)) //右右单旋
					AVL = SingleRightRotation(AVL);
				else	// if(AVL->Right->Right->Height < AVL->Right->Left->Height)	//右左双旋
					AVL = DoubleRightLeftRotation(AVL);
		}
		else if(x > AVL->Data)
		{
			AVL->Right = Delete(AVL->Right, x);
			if (GetHeight(AVL->Left) - GetHeight(AVL->Right) == 2)
				if (GetHeight(AVL->Left->Left) >= GetHeight(AVL->Left->Right))
					AVL = SingleLeftRotation(AVL);
				else
					AVL = DoubleLeftRightRotation(AVL);
		}
		else	//先Find要删除的位置
		{
			if(AVL->Left && AVL->Right)	//有左右两个孩子
			{
				if (GetHeight(AVL->Left) < GetHeight(AVL->Right)) //要删除结点的右子树更高, 则从右子树找一个Min
				{
					Tmp = FindMin(AVL->Right); //右子树的最小值
					AVL->Data = Tmp->Data;
					AVL->Right = Delete(AVL->Right, AVL->Data);	//转换为删除只有1个或0个孩子的请况
				}
				else
				{
					Tmp = FindMax(AVL->Left);
					AVL->Data = Tmp->Data;
					AVL->Left = Delete(AVL->Left, AVL->Data);
				}
			}
			else	//只有1个或0个孩子
			{
				Tmp = AVL;
				if(!AVL->Left)	//如果左子树为空
					AVL = AVL->Right;
				else
					AVL = AVL->Left;
				delete Tmp;
			}
		}
	}
	if (AVL)		//更新树高
		AVL->Height = max(GetHeight(AVL->Left), GetHeight(AVL->Right)) + 1;
	return AVL;
}

删除演示

1~10个数字一次插入AVLTree中
在这里插入图片描述
删除1
在这里插入图片描述
删除2
在这里插入图片描述
删除3
在这里插入图片描述
删除4
在这里插入图片描述
删除5
在这里插入图片描述
删除6
在这里插入图片描述
删除7
在这里插入图片描述
删除8
在这里插入图片描述
删除9
在这里插入图片描述
删除10, 结束

代码实现


对上述演示

input:
10
1 2 3 4 5 6 7 8 9 10
output:
中序遍历:
1 H= 1
2 H= 2
3 H= 1
4 H= 4
5 H= 1
6 H= 2
7 H= 1
8 H= 3
9 H= 2
10 H= 1

删除1?
2 H= 2
3 H= 1
4 H= 4
5 H= 1
6 H= 2
7 H= 1
8 H= 3
9 H= 2
10 H= 1
删除2?
3 H= 1
4 H= 3
5 H= 1
6 H= 2
7 H= 1
8 H= 4
9 H= 2
10 H= 1
删除3?
4 H= 2
5 H= 1
6 H= 3
7 H= 1
8 H= 4
9 H= 2
10 H= 1
删除4?
5 H= 1
6 H= 2
7 H= 1
8 H= 3
9 H= 2
10 H= 1
删除5?
6 H= 2
7 H= 1
8 H= 3
9 H= 2
10 H= 1
删除6?
7 H= 1
8 H= 3
9 H= 2
10 H= 1
删除7?
8 H= 1
9 H= 2
10 H= 1
删除8?
9 H= 2
10 H= 1
删除9?
10 H= 1
删除10?
请按任意键继续. . .

完整代码


balanced_binary_tree.h

#include <iostream>
#include <algorithm>
using namespace std;

typedef struct AVLTNode{
	int Data;
	AVLTNode *Left;
	AVLTNode *Right;
	int Height;	//树高
} * AVLTree;

/*获得树高*/
int GetHeight(AVLTree AVL)
{
	if (!AVL)
		return 0;
	else
		return AVL->Height;
}

/*LL左单旋算法*/
AVLTree SingleLeftRotation(AVLTree A)	//能进入这一步A必须有一个左子结点B
{
	AVLTree B = A->Left;
	A->Left = B->Right;		//第1步
	B->Right = A;			//第2步
	/*当已经完成旋转后, 调整树高*/
	A->Height = max(GetHeight(A->Left), GetHeight(A->Right)) + 1;	//注意从下往上调整
	B->Height = max(GetHeight(B->Left), A->Height) + 1;

	return B;	//返回树的根结点地址
}
/*RR右单旋算法, 与LL算法一样*/
AVLTree SingleRightRotation(AVLTree A)
{
	AVLTree B = A->Right;
	A->Right = B->Left;
	B->Left = A;
	A->Height = max(GetHeight(A->Left), GetHeight(A->Right)) + 1; //注意从下往上调整
	B->Height = max(GetHeight(B->Left), A->Height) + 1;

	return B;
}
/*左-右双旋算法*/
AVLTree DoubleLeftRightRotation(AVLTree A)	//A必须有1个左子结点B, B必须有1个右子结点C
{
	/*将B与C作右单旋, C被返回*/
	A->Left = SingleRightRotation(A->Left);
	/*将A与C作左单旋, C被返回*/
	return SingleLeftRotation(A);
}
/*右-左单旋算法*/
AVLTree DoubleRightLeftRotation(AVLTree A)
{
	A->Right = SingleLeftRotation(A->Right);
	return SingleRightRotation(A);
}


/*AVL树的插入*/
AVLTree Insert(AVLTree AVL, int x)	//将x插入AVL树中, 并返回调整后的AVL树
{	/*递归算法*/
	if(!AVL)	//AVL是空树或递归到空结点时, 准备插入x, 作为新的叶结点
	{
		AVL = new AVLTNode();
		AVL->Data = x;
		AVL->Height = 1;
	}
	else if(x < AVL->Data)	//Find要插入的位置
	{
		AVL->Left = Insert(AVL->Left, x);	//递归的Find
		/*完成元素插入后, 判断是否要左旋*/
		if(GetHeight(AVL->Left) - GetHeight(AVL->Right) == 2)
			if(x < AVL->Left->Data)	//插入位置在当前AVL根的左左
				AVL = SingleLeftRotation(AVL);
			else
				AVL = DoubleLeftRightRotation(AVL);
	}
	else if(x > AVL->Data)
	{
		AVL->Right = Insert(AVL->Right, x);
		if(GetHeight(AVL->Right) - GetHeight(AVL->Left) == 2)	//此时右子树插入后高度可能 + 1
			if(x > AVL->Right->Data)
				AVL = SingleRightRotation(AVL);
			else
				AVL = DoubleRightLeftRotation(AVL);
	}
	//else	树中已经有x, 什么也不做

	/*完成上述插入并调整后, 更新树高*/
	AVL->Height = max(GetHeight(AVL->Left), GetHeight(AVL->Right)) + 1;
	return AVL;
}

AVLTree FindMin(AVLTree AVL)
{
	if(AVL)
		while(AVL->Left)
			AVL = AVL->Left;
	return AVL;
}
AVLTree FindMax(AVLTree AVL)
{
	if(!AVL)
		return NULL;
	else if(AVL->Right)	//向右递归
		return FindMax(AVL->Right);
	else
		return AVL;
}

/*AVL树的删除*/
AVLTree Delete(AVLTree AVL, int x)
{
	AVLTree Tmp;
	if(!AVL)
		cout << "No" << endl;
	else
	{
		if(x < AVL->Data)
		{
			AVL->Left = Delete(AVL->Left, x);
			if(GetHeight(AVL->Right) - GetHeight(AVL->Left) == 2)	//即删除左边的可能会导致左边高减少
				if (GetHeight(AVL->Right->Right) >= GetHeight(AVL->Right->Left)) //右右单旋
					AVL = SingleRightRotation(AVL);
				else	// if(AVL->Right->Right->Height < AVL->Right->Left->Height)	//右左双旋
					AVL = DoubleRightLeftRotation(AVL);
		}
		else if(x > AVL->Data)
		{
			AVL->Right = Delete(AVL->Right, x);
			if (GetHeight(AVL->Left) - GetHeight(AVL->Right) == 2)
				if (GetHeight(AVL->Left->Left) >= GetHeight(AVL->Left->Right))
					AVL = SingleLeftRotation(AVL);
				else
					AVL = DoubleLeftRightRotation(AVL);
		}
		else	//先Find要删除的位置
		{
			if(AVL->Left && AVL->Right)	//有左右两个孩子
			{
				if (GetHeight(AVL->Left) < GetHeight(AVL->Right)) //要删除结点的右子树更高, 则从右子树找一个Min
				{
					Tmp = FindMin(AVL->Right); //右子树的最小值
					AVL->Data = Tmp->Data;
					AVL->Right = Delete(AVL->Right, AVL->Data);	//转换为删除只有1个或0个孩子的请况
				}
				else
				{
					Tmp = FindMax(AVL->Left);
					AVL->Data = Tmp->Data;
					AVL->Left = Delete(AVL->Left, AVL->Data);
				}
			}
			else	//只有1个或0个孩子
			{
				Tmp = AVL;
				if(!AVL->Left)	//如果左子树为空
					AVL = AVL->Right;
				else
					AVL = AVL->Left;
				delete Tmp;
			}
		}
	}
	if (AVL) //更新树高
		AVL->Height = max(GetHeight(AVL->Left), GetHeight(AVL->Right)) + 1;
	return AVL;
}

mainAVL.cpp

#include "balanced_binary_tree.h"
#include <algorithm>
using namespace std;

void Print(const AVLTree AVL)
{
	if(AVL)
	{
		Print(AVL->Left);
		cout << AVL->Data << " H= " << AVL->Height << endl;
		Print(AVL->Right);
	}
}

int main()
{
	AVLTree AVL = NULL;
	int n;
	cin >> n;
	int *num = new int[n];
	for (int i = 0; i < n; i++)
	{
		cin >> num[i];
		getchar();
		AVL = Insert(AVL, num[i]);
	}
	cout << "中序遍历: " << endl;
	Print(AVL);
	cout << endl;
	//return 1;
	for (int i = 0; i < n; i++)
	{
		cout << "删除" << num[i] << "?";
		getchar();
		AVL = Delete(AVL, num[i]);
		Print(AVL);
	}
	delete[] num;

	system("pause");
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值