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

来源:互联网 发布:动漫手机主题软件 编辑:程序博客网 时间:2024/06/14 05:24

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

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

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

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

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

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

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

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

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

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



#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 nodereturn 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   31*/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   33*/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 32     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 32  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;elsereturn FindMin(treeNode->left);}AVLTreeNode *FindMax(AVLTreeNode *treeNode){if (treeNode == NULL)return NULL;else if (treeNode->right == NULL)return treeNode;elsereturn 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-leftRotateWithLeftChild(treeNode);else//left-rightDoubleWithLeftChild(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);elseDoubleWithRightChild(treeNode);}}else;//duplicate, do nothing//it's impossible that treeNode is NULL here//so update it's height is safetreeNode->height = max(GetHeight(treeNode->left),GetHeight(treeNode->right)) + 1;}void Remove(AVLTreeNode *&treeNode, int data){if(treeNode == NULL)//not foundreturn;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);elseDoubleWithRightChild(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);elseDoubleWithLeftChild(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 heightif(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 insertint b[] = {2,1,3,4};//test removeAVLTreeNode *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;}


0 0