平衡二叉树的详解
参考慕课课程 https://www.icourse163.org/learn/ZJU-93001?tid=1003013004#/learn/content?type=detail&id=1004242207&cid=1005239477
参考数据结构与算法分析----C语言描述
如有错误,请指出
树的结构
typedef struct AVLNode *Position;
typedef Position AVLTree; /* AVL树类型 */
struct AVLNode {
int Data; /* 结点数据 */
AVLTree Left; /* 指向左子树 */
AVLTree Right; /* 指向右子树 */
int Height; /* 树高 */
};
建立一颗空树
AVLTree createTree(AVLTree T)
{
if (T)
{
createTree(T->Left);
createTree(T->Right);
free(T);
}
return NULL;
}
得到树节点的高度
int GetHeight(Position T)
{
if (T == NULL)
{
return -1;
}
else
return T->Height;
找到最大节点
AVLTree FindMax(AVLTree T)
{
if (T)
while (T->Right)
T = T->Right;
return T;
}
判断两个数大小
int Max(int a,int b)
{
return a > b ? a : b;
}
平衡二叉树的四种调整方式
右单旋
AVLTree SingleRotateWithRight(Position K) //右单旋
{
Position K1;
K1 = K->Right;
K->Right = K1->Left;
K1->Left = K;
K->Height = Max(GetHeight(K->Left), GetHeight(K->Right))+1; //重新调整树的高度
K1->Height = Max(GetHeight(K1->Left), GetHeight(K1->Right))+1; // 重新调整树的高度
return K1;
}
左单旋
AVLTree SingleRotateWithLeft(Position K) //左单旋
{
Position K1;
K1 = K->Left;
K->Left = K1->Right;
K1->Right = K;
K->Height = Max(GetHeight(K->Left), GetHeight(K->Right))+1; //重新调整树的高度
K1->Height = Max(GetHeight(K1->Left), GetHeight(K1->Right))+1; //重新调整树的高度
return K1;
}
左右双旋
AVLTree DoubleRotateWithLeft(Position K) // 左右双旋
{
K->Left = SingleRotateWithRight(K->Left); //先右旋
return SingleRotateWithLeft(K); // 后左旋
}
右左双旋
AVLTree DoubleRotateWithRight(Position K) // 右左双旋
{
K->Right = SingleRotateWithLeft(K->Right); //先左旋
return SingleRotateWithRight(K); // 后右旋
}
看图片理解代码
看不懂可以在机器上运行,看运行的过程
插入操作
AVLTree InsertTree(AVLTree T,int X)
{
if (T == NULL)
{
T = (AVLTree)malloc(sizeof(struct AVLNode));
T->Data = X;
T->Height = 0;
T->Left = T->Right = NULL;
}
else if (T->Data < X) // 向右插入
{
T->Right = InsertTree(T->Right, X);
if (GetHeight(T->Right) - GetHeight(T->Left) == 2) //在插入后检测树的平衡性
{
if (T->Right->Data < X) // 插入节点在右子树上,做单右旋转
{
T = SingleRotateWithRight(T);
}
else // 插入节点在左子树做右左双旋
{
T = DoubleRotateWithRight(T);
}
}
}
else if (T->Data > X) //向左插入
{
T->Left = InsertTree(T->Left, X);
if (GetHeight(T->Left) - GetHeight(T->Right) == 2) //在插入后检测树的平衡性
{
if (T->Left->Data > X) //插入节点在左子树,做单左旋转
{
T = SingleRotateWithLeft(T);
}
else // 插入节点在右子树 ,做左右双旋
{
T = DoubleRotateWithLeft(T);
}
}
}
T->Height = Max(GetHeight(T->Left), GetHeight(T->Right))+1; // 插入完成后,更新树的高度
return T;
}
删除操作
与二叉树的删除一致,只是删除之后要检测二叉树是不是平衡,更新二叉树各个节点的高度
AVLTree DeleteTree(AVLTree T, int X)
{
AVLTree Tmp;
if (T == NULL)
{
return NULL;
}
if (X < T->Data) // 向左查找删除
{
T->Left = DeleteTree(T->Left, X);
T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1; // 删除之后更新节点的高度
if (GetHeight(T->Right) - GetHeight(T->Left) == 2) //判断是否平衡
{
AVLTree tmp = T->Right; //此处应该判断T->Right不为空
if (GetHeight(tmp->Left) > GetHeight(tmp->Right)) // 左子树节点高,做右左双旋
T = DoubleRotateWithRight(T);
else // 右子树高,做单右旋转
T = SingleRotateWithRight(T);
}
}
else if (X > T->Data) //向右查找删除
{
T->Right = DeleteTree(T->Right, X);
T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1; //更新树的高度
if (GetHeight(T->Left) - GetHeight(T->Right) == 2) // 判断树是否平衡
{
AVLTree tmp = T->Left; // 此处应该判断 T->Left 不为空
if (GetHeight(tmp->Right) > GetHeight(tmp->Left)) //右子树高,做左右双旋
{
T = DoubleRotateWithLeft(T);
}
else // 左子树高,做单左旋转
{
T = SingleRotateWithLeft(T);
}
}
}
else
{
if (T->Left && T->Right)
{
Tmp = FindMax(T->Left); // 找出左子树最大节点,代替被删除节点
T->Data = Tmp->Data;
T->Left = DeleteTree(T->Left, T->Data);
}
else
{
Tmp = T;
if (T->Left == NULL)
{
T = T->Right;
}
else if (T->Right == NULL)
{
T = T->Left;
}
free(Tmp);
}
}
return T;
}