AVL树是一种最原始的二叉查找树,它的各个节点的左右子树高度不超过1,因此能保证树的高度最大值为Olog(N),从而大大提高查找、插入、删除等操作的效率。在插入和删除元素时通过旋转操作使得AVL保持原有特性。本文给出了AVL树四种旋转操作和插入操作的C语言程序。
四种旋转操作参考《数据结构与算法分析——C语言描述第二版》。
插入操作则是在BST树查找函数框架的基础上进行改进,如果插入完成后AVL不再平衡,则根据条件进行旋转使树平衡。注意在旋转或插入完成后更新高度!本文中空节点高度设为-1。
#include
#include
typedef struct AVLNode{
int data;
struct AVLNode* lchild;
struct AVLNode* rchild;
int height;//保存高度信息。
} AVLNode, *AVLTree, *Position;
int Height(Position T);
int Max(int a, int b);
Position SingleRotateWithLeft(Position k2);
Position SingleRotateWithRight(Position k2);
Position DoubleRotateWithLeft(Position k3);
Position DoubleRotateWithRight(Position k3);
AVLTree Insert(int data, AVLTree T);
AVLTree Delete(int tar, AVLTree T);
void ProOrderTraversal(AVLTree T);
Position Find(int tar, AVLTree T);
Position FindMin(AVLTree T);
Position FindMax(AVLTree T);
//测试数据来自《数据结构与算法分析——C语言描述》
void main()
{
AVLTree T = NULL;
T = Insert(3, T);
T = Insert(2, T);
T = Insert(1, T);
printf("前序遍历结果为:");
ProOrderTraversal(T);
printf("\n");
T = Insert(4, T);
T = Insert(5, T);
T = Insert(6, T);
T = Insert(7, T);
printf("前序遍历结果为:");
ProOrderTraversal(T);
printf("\n");
T = Insert(16, T);
T = Insert(15, T);
T = Insert(14, T);
T = Insert(13, T);
T = Insert(12, T);
T = Insert(11, T);
T = Insert(10, T);
T = Insert(8, T);
T = Insert(9, T);
printf("前序遍历结果为:");
ProOrderTraversal(T);
printf("\n");
}
int Height(Position T)
{
if (!T)//空节点高度为-1
return -1;
else
return T->height;
}
int Max(int a, int b)
{
return (a > b) ? a : b;
}
Position SingleRotateWithLeft(Position k2)//LL旋转
{
Position k1;
k1 = k2->lchild;
k2->lchild = k1->rchild;
k1->rchild = k2;
k2->height = Max(Height(k2->lchild), Height(k2->rchild)) + 1;//更新k2节点的高度!
k1->height = Max(Height(k1->lchild), Height(k1->rchild)) + 1;//更新k1节点的高度!
return k1;
}
Position SingleRotateWithRight(Position k2)//RR旋转
{
Position k1;
k1 = k2->rchild;
k2->rchild = k1->lchild;
k1->lchild = k2;
k2->height = Max(Height(k2->lchild), Height(k2->rchild)) + 1;//更新k2节点的高度!
k1->height = Max(Height(k1->lchild), k2->height) + 1;//更新k1节点的高度!
return k1;
}
Position DoubleRotateWithLeft(Position k3)//LR旋转
{
k3->lchild = SingleRotateWithRight(k3->lchild);
return SingleRotateWithLeft(k3);
}
Position DoubleRotateWithRight(Position k3)//RL旋转
{
k3->rchild = SingleRotateWithLeft(k3->rchild);
return SingleRotateWithRight(k3);
}
AVLTree Insert(int data, AVLTree T)
{
if (!T)//找到插入位置,进行插入
{
T = (AVLTree)malloc(sizeof(AVLNode));
T->data = data;
T->height = 0;
T->lchild = T->rchild = NULL;
}
else if (data < T->data)//进行左子树递归插入
{
T->lchild = Insert(data, T->lchild);
if (Height(T->lchild) - Height(T->rchild) == 2)
{
if (data < T->lchild->data)
T = SingleRotateWithLeft(T);
else
T = DoubleRotateWithLeft(T);
}
}
else if (data > T->data)//进行右子树递归插入
{
T->rchild = Insert(data, T->rchild);
if (Height(T->lchild) - Height(T->rchild) == -2)
{
if (data > T->rchild->data)
T = SingleRotateWithRight(T);
else
T = DoubleRotateWithRight(T);
}
}
else//插入失败
printf("AVL树已有该元素,插入失败");
T->height = Max(Height(T->lchild), Height(T->rchild)) + 1; //更新树的高度!
return T;
}
void ProOrderTraversal(AVLTree T)
{
if (T)
{
printf("%d ", T->data);
ProOrderTraversal(T->lchild);
ProOrderTraversal(T->rchild);
}
}
Position Find(int tar, AVLTree T)
{
if (!T)
return NULL;
else if (tar < T->data)
return Find(tar, T->lchild);
else if (tar > T->data)
return Find(tar, T->rchild);
else
return T;
}
Position FindMin(AVLTree T)
{
if (!T)
return NULL;
else if (!T->lchild)
return T;
else
return FindMin(T->lchild);
}
Position FindMax(AVLTree T)
{
if (T)
{
while (T && T->rchild)
T = T->rchild;
}
return T;
}