AVL树的C++实现 Implement of AVL tree

AVL是一种自平衡的二叉查找树。

不同于普通的二叉查找树之处在于:每个节点的左右子树高度差最多为1,故每个节点多了一个高度(height)属性。

其实现难点在于插入和删除时要检测节点高度差是否满足上述条件,当超过1时,分四种情况进行调节。

case1:左儿子的左子树插入值 left-left

case2:左儿子的右子树插入值 left-right

case3:右儿子的左子树插入值 right-left

case4:右儿子的右子树插入值 right-right

以上四种情况中,虽然删除操作不是“插入值”,但是删除后导致的结果可以转换成插入来看待处理。

为了简便说明原理,此处仅对删除操作的一种类型作图说明。

以下,删除的值在左侧时,即remove函数中treeNode->val > data的情况。

《AVL树的C++实现 Implement of AVL tree》《AVL树的C++实现 Implement of AVL tree》

《AVL树的C++实现 Implement of AVL tree》

#include <queue>
#include <iostream>
using namespace std;
struct AVLTreeNode
{
	int val;
	int height;
	AVLTreeNode *left;
	AVLTreeNode *right;
};

int GetHeight(AVLTreeNode *treeNode)
{
	//must update this height when insert or move a node
	return treeNode == NULL ? -1 : treeNode->height;

	//if use the code below,there is no need to use member "height"
	//and there is no need to update height anymore
	//but it may cost much time as it uses recursion to get the height every time
	/*if(treeNode == NULL)
		return -1;
	return 1 + max(GetHeight(treeNode->left), GetHeight(treeNode->right));*/
}

//case 1,add "1" to 3,2(left-left)
/*
	3         2
  2    ->   1   3
1
*/
void RotateWithLeftChild(AVLTreeNode *&treeNode)
{
	AVLTreeNode *p = treeNode->left;
	treeNode->left = p->right;
	p->right = treeNode;
	treeNode->height = max(GetHeight(treeNode->left), GetHeight(treeNode->right)) + 1;
	p->height =  max(GetHeight(p->left), treeNode->height) + 1;
	treeNode = p;
}

//case 4,add "3" to 1,2(right-right)
/*
1			  2
  2    ->   1   3
	3
*/
void RotateWithRightChild(AVLTreeNode *&treeNode)
{
	AVLTreeNode *p = treeNode->right;
	treeNode->right = p->left;
	p->left = treeNode;
	treeNode->height = max(GetHeight(treeNode->left), GetHeight(treeNode->right)) + 1;
	p->height = max(GetHeight(p->right), treeNode->height) + 1;
	treeNode = p;
}

//case 2,add "2" to 3,1(left-right)
/*
	3	      3      2
  1    ->   2   ->  1 3
	2     1
*/
void DoubleWithLeftChild(AVLTreeNode *&treeNode)
{
	RotateWithRightChild(treeNode->left);
	RotateWithLeftChild(treeNode);
}

//case 3,add "2" to 1,3(right-left)
/*
1	      1          2
  3    ->   2   ->  1 3
2			  3
*/
void DoubleWithRightChild(AVLTreeNode *&treeNode)
{
	RotateWithLeftChild(treeNode->right);
	RotateWithRightChild(treeNode);
}

AVLTreeNode *FindMin(AVLTreeNode *treeNode)
{
	if(treeNode == NULL)
		return NULL;
	else if(treeNode->left == NULL)
		return treeNode;
	else
		return FindMin(treeNode->left);
}

AVLTreeNode *FindMax(AVLTreeNode *treeNode)
{
	if (treeNode == NULL)
		return NULL;
	else if (treeNode->right == NULL)
		return treeNode;
	else
		return FindMax(treeNode->right);
}

void Insert(AVLTreeNode *&treeNode, int data)
{
	if(treeNode == NULL)
	{
		treeNode = new AVLTreeNode;
		treeNode->left = NULL;
		treeNode->right = NULL;
		treeNode->val = data;
	}

	else if (treeNode->val > data)//go to left subtree
	{
		Insert(treeNode->left,data);
		if (GetHeight(treeNode->left) - GetHeight(treeNode->right) == 2)
		{
			if(data < treeNode->left->val) //left-left
				RotateWithLeftChild(treeNode);
			else							//left-right
				DoubleWithLeftChild(treeNode);
		}
	}

	else if (treeNode->val < data) //go to right subtree
	{
		Insert(treeNode->right,data);
		if(GetHeight(treeNode->right) - GetHeight(treeNode->left) == 2)
		{
			if (data > treeNode->right->val)
				RotateWithRightChild(treeNode);
			else
				DoubleWithRightChild(treeNode);
		}
	}

	else
		;//duplicate, do nothing

	//it's impossible that treeNode is NULL here
	//so update it's height is safe
	treeNode->height = max(GetHeight(treeNode->left),GetHeight(treeNode->right)) + 1;
}

void Remove(AVLTreeNode *&treeNode, int data)
{
	if(treeNode == NULL)//not found
		return;
	if (treeNode->val > data) //go to left subtree
	{
		Remove(treeNode->left,data);
		if (GetHeight(treeNode->right) - GetHeight(treeNode->left) == 2)
		{
			if(treeNode->right->right != NULL)
				RotateWithRightChild(treeNode);
			else
				DoubleWithRightChild(treeNode);
		}
	}
	else if (treeNode->val < data) //go to right subtree
	{
		Remove(treeNode->right,data);
		if (GetHeight(treeNode->left) - GetHeight(treeNode->right) == 2)
		{
			if (treeNode->left->left != NULL)
				RotateWithLeftChild(treeNode);
			else 
				DoubleWithLeftChild(treeNode);
		}
	}
	else if(treeNode->left != NULL && treeNode->right != NULL)//found,has two children
	{
		treeNode->val = FindMin(treeNode->right)->val;
		Remove(treeNode->right,treeNode->val);//not "data"!!
		if (GetHeight(treeNode->left) - GetHeight(treeNode->right) == 2)
		{
			if(treeNode->left->left != NULL)
				RotateWithLeftChild(treeNode);
			else
				DoubleWithLeftChild(treeNode);
		}
	}
	else // found,has one or no child
	{
		AVLTreeNode *tmp = treeNode;
		treeNode = (treeNode->left != NULL) ? treeNode->left : treeNode->right;
		delete tmp;
		tmp = NULL;
	}
	
	//if treeNode is NULL,treeNode->height will cause error
	//so if treeNode is a leaf, there is no need to update its height
	if(treeNode != NULL)
		treeNode->height = max(GetHeight(treeNode->left), GetHeight(treeNode->right)) + 1;
}

void LevelOrderTraverse(AVLTreeNode *root)
{
	if(root == NULL) return;

	queue<AVLTreeNode*> Q;
	Q.push(root);
	while(!Q.empty())
	{
		AVLTreeNode *p = Q.front();
		if (p->left != NULL)
			Q.push(p->left);
		if (p->right != NULL)
			Q.push(p->right);
		cout << p->val <<"("<<p->height<<") ";
		Q.pop();
	}
	cout << "\n";
}

void PreOrderTraverse(AVLTreeNode *treeNode)
{
	if (treeNode != NULL)
	{
		cout << treeNode->val <<"("<<treeNode->height<<") ";
		PreOrderTraverse(treeNode->left);
		PreOrderTraverse(treeNode->right);
	}
}

void InOrderTraverse(AVLTreeNode *treeNode)
{
	if (treeNode != NULL)
	{
		InOrderTraverse(treeNode->left);
		cout << treeNode->val <<"("<<treeNode->height<<") ";
		InOrderTraverse(treeNode->right);
	}
}

void PostOrderTraverse(AVLTreeNode *treeNode)
{
	if (treeNode != NULL)
	{
		PostOrderTraverse(treeNode->left);
		PostOrderTraverse(treeNode->right);
		cout << treeNode->val <<"("<<treeNode->height<<") ";
	}
}

void MakeEmpty(AVLTreeNode *&treeNode)
{
	if (treeNode != NULL)
	{
		MakeEmpty(treeNode->left);
		MakeEmpty(treeNode->right);
		delete treeNode;
	}
	treeNode = NULL;
}

void BuildAVLTree(AVLTreeNode *&root,int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		Insert(root,a[i]);
	}
}

int main(void)
{
	int a[] = {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};//test insert
	int b[] = {2,1,3,4};//test remove

	AVLTreeNode *root = NULL;
	//BuildAVLTree(root,a,sizeof(a)/sizeof(a[0]));
	BuildAVLTree(root,b,sizeof(b)/sizeof(b[0]));
	LevelOrderTraverse(root);
	
	Remove(root,4);
	PreOrderTraverse(root);
	cout << "\n";
	InOrderTraverse(root);
	cout << "\n";
	MakeEmpty(root);
	return 0;
}

    原文作者:AVL树
    原文地址: https://blog.csdn.net/pyang1989/article/details/22697121
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞