AVL树的旋转与插入操作

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;
}



你可能感兴趣的:(AVL树的旋转与插入操作)