一、AVL树的链式存储
typedef int ElementType;
typedef struct AVLNode *Position;
typedef Position AVLTree;
struct AVLNode{
ElementType Data;//结点数据
AVLTree Left;//指向左子树
AVLTree Right;//指向右子树
int Height;//树高
};
二、旋转
左单旋
AVLTree SingleLeftRotation(AVLTree A)
{
//A必须有一个左子节点B
//返回新的根节点B
printf("左单旋\n");
AVLTree B=A->Left ;
A->Left =B->Right ;
B->Right=A;
//更新树高
A->Height =Max(GetHeight(A->Left ),GetHeight(A->Right ))+1;
B->Height =Max(GetHeight(B->Left ),A->Height )+1;
return B;
}
右单旋
AVLTree SingleRightRotation(AVLTree A)
{
//A必须有一个右子节点B
//返回新的根节点A
printf("右单旋\n");
AVLTree B=A->Right ;
A->Right=B->Left ;
B->Left =A;
//更新树高
A->Height =Max(GetHeight(A->Left ),GetHeight(A->Right ))+1;
B->Height =Max(A->Height ,GetHeight(B->Right ))+1;
}
左右双旋
AVLTree DoubleLeftRightRotation(AVLTree A)
{
//A必须有一个左子节点B,B必须有一个右子节点C
//返回新的根节点C
printf("左右单旋\n");
//将B与C做右单旋 ,返回C
A->Left =SingleRightRotation(A->Left );
//将A与C做左单旋 ,返回C
return SingleLeftRotation(A);
}
右左双旋
AVLTree DoubleRightLeftRotation(AVLTree A)
{
//A必须有一个右子节点B,B必须有一个左子节点C
//返回新的根节点C
printf("右左单旋\n");
//将B与C做左单旋,返回C
A->Right=SingleLeftRotation(A->Right );
//将A与C做右单旋 ,返回C
return SingleRightRotation(A);
}
三、插入
AVLTree Insert(AVLTree T,ElementType X)
{
if(!T){
//插入空树
T=(AVLTree)malloc(sizeof(struct AVLNode));
T->Data =X;
T->Left =T->Right =NULL;
T->Height =1;
}//树非空,选择插入左子树还是右子树
else if(X<T->Data ){//插入左子树
T->Left =Insert(T->Left ,X);
//不平衡,需要左旋
if(GetHeight(T->Left )-GetHeight(T->Right )==2)//不平衡的条件
if(X<T->Left->Data ) //在左边
T=SingleLeftRotation(T);//左单旋
else //在右边
T=DoubleLeftRightRotation(T); //左右双旋
}
else if(X>T->Data ){//插入右子树
T->Right=Insert(T->Right ,X);
//不平衡
if(GetHeight(T->Right )-GetHeight(T->Left )==2)
if(X>T->Right->Data )//在右边
T=SingleRightRotation(T);//右单旋
else //在左边
T=DoubleRightLeftRotation(T);//右左双旋
}
//else X==T->Data不需要插入
//更新树高
T->Height =Max(GetHeight(T->Left ),GetHeight(T->Right ))+1; //选择左右子树的最大高度并加上树根高度
return T;
}
四、完整代码
//平衡二叉树AVL
//AVL树的插入操作的非递归算法可读性差,使用通常使用递归算法来实现
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
/*-------------AVL树的链式存储--------------------*/
typedef int ElementType;
typedef struct AVLNode *Position;
typedef Position AVLTree;
struct AVLNode{
ElementType Data;//结点数据
AVLTree Left;//指向左子树
AVLTree Right;//指向右子树
int Height;//树高
};
/*-------------AVL树的链式存储结束--------------------*/
//树高
int GetHeight(AVLTree T)
{
int LH,RH,MaxH;
if(T){
LH=GetHeight(T->Left );
RH=GetHeight(T->Right );
MaxH=LH>RH?LH:RH;
return (MaxH+1);//返回树高
}
return 0;//空树高度为1
}
//先序遍历
void PreorderTraversal(AVLTree T)
{
if(T){
printf("%d ",T->Data );
PreorderTraversal(T->Left );
PreorderTraversal(T->Right );
}
}
//最大值
int Max(int a,int b)
{
//返回a,b中的较大值
return a>b?a:b;
}
/*-------------旋转--------------------*/
//左单旋
AVLTree SingleLeftRotation(AVLTree A)
{
//A必须有一个左子节点B
//返回新的根节点B
printf("左单旋\n");
AVLTree B=A->Left ;
A->Left =B->Right ;
B->Right=A;
//更新树高
A->Height =Max(GetHeight(A->Left ),GetHeight(A->Right ))+1;
B->Height =Max(GetHeight(B->Left ),A->Height )+1;
return B;
}
//右单旋
AVLTree SingleRightRotation(AVLTree A)
{
//A必须有一个右子节点B
//返回新的根节点A
printf("右单旋\n");
AVLTree B=A->Right ;
A->Right=B->Left ;
B->Left =A;
//更新树高
A->Height =Max(GetHeight(A->Left ),GetHeight(A->Right ))+1;
B->Height =Max(A->Height ,GetHeight(B->Right ))+1;
}
//左右双旋
AVLTree DoubleLeftRightRotation(AVLTree A)
{
//A必须有一个左子节点B,B必须有一个右子节点C
//返回新的根节点C
printf("左右单旋\n");
//将B与C做右单旋 ,返回C
A->Left =SingleRightRotation(A->Left );
//将A与C做左单旋 ,返回C
return SingleLeftRotation(A);
}
//右左双旋
AVLTree DoubleRightLeftRotation(AVLTree A)
{
//A必须有一个右子节点B,B必须有一个左子节点C
//返回新的根节点C
printf("右左单旋\n");
//将B与C做左单旋,返回C
A->Right=SingleLeftRotation(A->Right );
//将A与C做右单旋 ,返回C
return SingleRightRotation(A);
}
/*-------------旋转结束--------------------*/
/*-------------插入函数--------------------*/
AVLTree Insert(AVLTree T,ElementType X)
{
if(!T){
//插入空树
T=(AVLTree)malloc(sizeof(struct AVLNode));
T->Data =X;
T->Left =T->Right =NULL;
T->Height =1;
}//树非空,选择插入左子树还是右子树
else if(X<T->Data ){//插入左子树
T->Left =Insert(T->Left ,X);
//不平衡,需要左旋
if(GetHeight(T->Left )-GetHeight(T->Right )==2)//不平衡的条件
if(X<T->Left->Data ) //在左边
T=SingleLeftRotation(T);//左单旋
else //在右边
T=DoubleLeftRightRotation(T); //左右双旋
}
else if(X>T->Data ){//插入右子树
T->Right=Insert(T->Right ,X);
//不平衡
if(GetHeight(T->Right )-GetHeight(T->Left )==2)
if(X>T->Right->Data )//在右边
T=SingleRightRotation(T);//右单旋
else //在左边
T=DoubleRightLeftRotation(T);//右左双旋
}
//else X==T->Data不需要插入
//更新树高
T->Height =Max(GetHeight(T->Left ),GetHeight(T->Right ))+1; //选择左右子树的最大高度并加上树根高度
return T;
}
/*-------------插入结束--------------------*/
//输出
void PrintResult(AVLTree T)
{
int h=GetHeight(T);
printf("树高为:%d\n",h);
printf("先序遍历:");
PreorderTraversal(T);
printf("\n");
}
int main()
{
AVLTree T=NULL,Head=NULL;;
ElementType X;
printf("请输入根节点:");
scanf("%d",&X);
T=Insert(T,X);
Head=T;
int i;
printf("请输入5个子节点:");
for(i=0;i<5;i++){
scanf("%d",&X);
T=Insert(T,X);
}
PrintResult(T);
return 0;
}
运行:
![](https://i-blog.csdnimg.cn/blog_migrate/5676b05ec7753b1e47ad5644208c5703.png)
![](https://i-blog.csdnimg.cn/blog_migrate/cd2a184558bfa73e9f741376c364b48e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0a790a0e98592a087f1b2a15ed335340.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8286762efeebe2363bb6ee8bf1d86896.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3db0eac05e6e4f3e787cafe518efe688.png)
![](https://i-blog.csdnimg.cn/blog_migrate/db66e9dda3054100fcb7b3bed48759d1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/390d7e30958ff574ceb93bb90f81e62d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/73bae5f1dfbe567f8c4623164feab119.png)