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) { 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 treeNode->height = max(GetHeight(treeNode->left),GetHeight(treeNode->right)) + 1; //TreeNode->height = max(TreeNode->left->height,TreeNode->right->height) + 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; if(treeNode != NULL) treeNode->height = max(GetHeight(treeNode->left), GetHeight(treeNode->right)); //if treeNode is NULL,treeNode->height will cause error //so if treeNode is a leaf, there is no need to update its height } } 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 << " "; Q.pop(); } cout << "\n"; } void PreOrderTraverse(AVLTreeNode *treeNode) { if (treeNode != NULL) { cout << treeNode->val << " "; PreOrderTraverse(treeNode->left); PreOrderTraverse(treeNode->right); } } void InOrderTraverse(AVLTreeNode *treeNode) { if (treeNode != NULL) { InOrderTraverse(treeNode->left); cout << treeNode->val << " "; InOrderTraverse(treeNode->right); } } void PostOrderTraverse(AVLTreeNode *treeNode) { if (treeNode != NULL) { PostOrderTraverse(treeNode->left); PostOrderTraverse(treeNode->right); cout << treeNode->val << " "; } } 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[] = {4,2,5,3};//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,1); PreOrderTraverse(root); cout << "\n"; InOrderTraverse(root); cout << "\n"; MakeEmpty(root); return 0; }
AVL树的实现 Implement of AVL tree,布布扣,bubuko.com
原文:http://blog.csdn.net/pyang1989/article/details/22697121