参考大佬: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;
}