(一个人感冒咳嗽不悲剧,悲剧的是全家都感冒咳嗽,没人做事……忽冷忽热的天气得注意保暖)
首先吧,关于AVL树的知识,还是老规矩,Wiki下。
“在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
节点的平衡因子是它的右子树的高度减去它的左子树的高度。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。”
这样,对AVL树就能大概理解了。然后吧,就来温习下主要的插入和删除操作实现。
其实,这个两个操作都可以分成两个步骤,一个是普通操作(删除、插入),另个是平衡操作。
普通操作,就是简单的寻找到需要删除或者插入的节点位置,把寻找路径保存起来(我用数组模拟栈保存)。对于插入操作,就直接将新节点插入到该位置即可。对于删除操作,则需要翻阅点资料了。也有两大类吧,删除同时有左右子树的节点,这样的话,就可以通过其中序前驱节点替换实现。如果说最多只有一棵子树,那么就好办了,就用子树替换吧。
平衡操作呢,也可以再细分成两个步骤。一个是树结构的变换,另一个是树节点平衡因子的更新。树结构的变换的话,可以看看四种旋转及其应用条件(http://tc.itkee.com/media/detail-a06.html这篇文章介绍得蛮详细的,就不多敲了)。然后平衡因子的更新,只用更新那几个子树结构变化了的节点。
这些理解了的话,那就容易理解我实现的AVL类了。(代码虽长,因为考虑到要缩小函数规模,功能分得比较细;另外,有专门用来测试的函数。个人资源有0分方便下载http://download.csdn.net/detail/betabin/4185761)
/*
Author:BetaBin
Date:2012/03/30
AboutMe:http://blog.csdn.net/BetaBin
*/
#include <iostream>
using namespace std;
#define MAX_DEPTH 32
//AVL树节点类
template <class NodeType>
class AvlNode
{
public:
int balancedfactor;
NodeType value;
AvlNode<NodeType> *lChild, *rChild;
AvlNode();
AvlNode(NodeType data);
};
template <class NodeType>
AvlNode<NodeType>::AvlNode()
{
balancedfactor = 0;
lChild = NULL;
rChild = NULL;
}
template <class NodeType>
AvlNode<NodeType>::AvlNode(NodeType data)
{
balancedfactor = 0;
lChild = NULL;
rChild = NULL;
value = data;
}
//AVL树模板类
template <class NodeType>
class AvlTree
{
public:
AvlTree();
~AvlTree();
void DestroyTree(AvlNode<NodeType> *node); //销毁以node为根的AVL树
bool InsertValue(NodeType value); //插入新值value
bool RemoveValue(NodeType value); //移除值为value的节点
AvlNode<NodeType>* GetRoot(); //获取Root指针
void InfixOutput(AvlNode<NodeType> *node); //中序输出节点信息,用于测试。NodeType必须重载<<输出符号
private:
AvlNode<NodeType> *root; //根节点
AvlNode<NodeType> *path[MAX_DEPTH]; //实现路径保存栈
int pathLen; //路径实际长度 - 1,配合path数组模拟栈
//四种旋转
AvlNode<NodeType>* LLRotate(AvlNode<NodeType> *rotateRoot);
AvlNode<NodeType>* LRRotate(AvlNode<NodeType> *rotateRoot);
AvlNode<NodeType>* RRRotate(AvlNode<NodeType> *rotateRoot);
AvlNode<NodeType>* RLRotate(AvlNode<NodeType> *rotateRoot);
bool FindPosition(NodeType value); //用于插入函数,寻找存放value的位置,并插入,保存寻找路径至path数组。节点已经存在则返回false,否则为true
void InsertBalanced(NodeType value); //插入操作后平衡树
void RemoveBalanced(NodeType value); //删除操作后平衡树
bool RotateTree(); //用于旋转树(以当前path[pathLen]为根节点的树),并且判断该子树旋转后高度是否变化,变化返回true,否则返回false
void RemoveNode(AvlNode<NodeType> *node); //用于删除该节点,并且更新平衡因子信息
};
template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::GetRoot()
{
return root;
}
template <class NodeType>
void AvlTree<NodeType>::InfixOutput(AvlNode<NodeType> *node)
{
if (NULL == node)
{
return ;
}
InfixOutput(node->lChild);
cout << "### " << node->value << endl;
InfixOutput(node->rChild);
}
template <class NodeType>
AvlTree<NodeType>::AvlTree()
{
root = NULL;
pathLen = 0;
}
template <class NodeType>
AvlTree<NodeType>::~AvlTree()
{
DestroyTree(root);
}
template <class NodeType>
void AvlTree<NodeType>::DestroyTree(AvlNode<NodeType> *node)
{
if (NULL == node)
{
return ;
}
DestroyTree(node->lChild);
DestroyTree(node->rChild);
delete node;
}
template <class NodeType>
bool AvlTree<NodeType>::FindPosition(NodeType value)
{
pathLen = 0;
AvlNode<NodeType> *prevnode = NULL;
AvlNode<NodeType> *currentnode = root;
//保存从根到值为value的节点该存放位置的路径到模拟栈中
while (currentnode != NULL)
{
path[pathLen++] = currentnode;
//原值已经存在,插入查找失败
if (currentnode->value == value)
{
return false;
}
prevnode = currentnode;
if (currentnode->value < value)
{
currentnode = currentnode->rChild;
}
else
{
currentnode = currentnode->lChild;
}
}
//将该value值插入到相应位置
currentnode = new AvlNode<NodeType>(value);
currentnode->balancedfactor = 0;
if (value < prevnode->value)
{
prevnode->lChild = currentnode;
}
else
{
prevnode->rChild = currentnode;
}
path[pathLen] = currentnode;
return true;
}
template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::LLRotate(AvlNode<NodeType> *rotateRoot)
{
//树结构变换
AvlNode<NodeType> *newRoot = rotateRoot->lChild;
rotateRoot->lChild = newRoot->rChild;
newRoot->rChild = rotateRoot;
//平衡因子调整
if (1 == newRoot->balancedfactor)
{
rotateRoot->balancedfactor = 0;
newRoot->balancedfactor = 0;
}
//删除操作出现平衡因子为0
else
{
rotateRoot->balancedfactor = 1;
newRoot->balancedfactor = -1;
}
return newRoot;
}
template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::LRRotate(AvlNode<NodeType> *rotateRoot)
{
//树结构变换
AvlNode<NodeType> *nextNode = rotateRoot->lChild;
AvlNode<NodeType> *newRoot = nextNode->rChild;
rotateRoot->lChild = newRoot->rChild;
nextNode->rChild = newRoot->lChild;
newRoot->rChild = rotateRoot;
newRoot->lChild = nextNode;
//平衡因子调整
switch (newRoot->balancedfactor)
{
case 0:
rotateRoot->balancedfactor = 0;
nextNode->balancedfactor = 0;
break;
case 1:
rotateRoot->balancedfactor = -1;
nextNode->balancedfactor = 0;
break;
case -1:
rotateRoot->balancedfactor = 0;
nextNode->balancedfactor = 1;
break;
default:
return NULL;
}
newRoot->balancedfactor = 0;
return newRoot;
}
template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::RRRotate(AvlNode<NodeType> *rotateRoot)
{
//树结构变换
AvlNode<NodeType>* newRoot = rotateRoot->rChild;
rotateRoot->rChild = newRoot->lChild;
newRoot->lChild = rotateRoot;
//平衡因子调整
if (-1 == newRoot->balancedfactor)
{
rotateRoot->balancedfactor = 0;
newRoot->balancedfactor = 0;
}
else
{
rotateRoot->balancedfactor = -1;
newRoot->balancedfactor = 1;
}
return newRoot;
}
template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::RLRotate(AvlNode<NodeType> *rotateRoot)
{
//树结构调整
AvlNode<NodeType>* nextNode = rotateRoot->rChild;
AvlNode<NodeType>* newRoot = nextNode->lChild;
rotateRoot->rChild = newRoot->lChild;
nextNode->lChild = newRoot->rChild;
newRoot->lChild = rotateRoot;
newRoot->rChild = nextNode;
//平衡因子调整
switch (newRoot->balancedfactor)
{
case 0:
rotateRoot->balancedfactor = 0;
nextNode->balancedfactor = 0;
break;
case 1:
rotateRoot->balancedfactor = 0;
nextNode->balancedfactor = -1;
break;
case -1:
rotateRoot->balancedfactor = 1;
nextNode->balancedfactor = 0;
break;
default:
return NULL;
}
newRoot->balancedfactor = 0;
return newRoot;
}
//根据平衡因子判断需要进行的旋转类型,并进行旋转操作
//同时判断旋转之后树高度是否变化,用于删除操作
//高度变化返回true,否则返回false
template <class NodeType>
bool AvlTree<NodeType>::RotateTree()
{
bool isHeightChanged = true;
AvlNode<NodeType> *oldRoot = path[pathLen]; //通过模拟栈找到需要调整的根
AvlNode<NodeType> *newRoot;
int originalRootBf = oldRoot->balancedfactor;
if (2 == originalRootBf)
{
int leftBf = oldRoot->lChild->balancedfactor;
if (1 == leftBf)
{
newRoot = LLRotate(oldRoot);
}
else if (-1 == leftBf)
{
newRoot = LRRotate(oldRoot);
}
//删除操作会出现平衡因子为0的情况
else
{
newRoot = LLRotate(oldRoot);
isHeightChanged = false;
}
}
if (-2 == originalRootBf)
{
int rightBf = oldRoot->rChild->balancedfactor;
if (1 == rightBf)
{
newRoot = RLRotate(oldRoot);
}
else if (-1 == rightBf)
{
newRoot = RRRotate(oldRoot);
}
//删除操作会出现平衡因子为0的情况
else
{
newRoot = RRRotate(oldRoot);
isHeightChanged = false;
}
}
//更新根的父亲节点的指针
if (pathLen > 0)
{
if (oldRoot->value < path[pathLen - 1]->value)
{
path[pathLen - 1]->lChild = newRoot;
}
else
{
path[pathLen - 1]->rChild = newRoot;
}
}
else
{
root = newRoot;
}
return isHeightChanged;
}
template <class NodeType>
void AvlTree<NodeType>::InsertBalanced(NodeType value)
{
int bf = 0;
while (pathLen > 0)
{
bf = (path[pathLen - 1]->value > value) ? 1 : -1;
path[--pathLen]->balancedfactor += bf;
bf =path[pathLen]->balancedfactor;
//遇到平衡因子变为1或者-1表示该子树平衡没有遭到破坏,既可以不用再平衡其祖宗
if (0 == bf)
{
break;
}
else if (2 == bf || -2 == bf)
{
RotateTree();
}
}
}
template<class NodeType>
void AvlTree<NodeType>::RemoveBalanced(NodeType value)
{
int bf = 0;
while (pathLen > 0)
{
bf = (path[pathLen - 1]->value >= value) ? -1 : 1;
path[--pathLen]->balancedfactor += bf;
bf = path[pathLen]->balancedfactor;
if (0 != bf)
{
//遇到平衡因子变为1或者-1表示该子树平衡没有遭到破坏,既可以不用再平衡其祖宗
//删除操作后,遇到树高度不变化,也可不用再平衡其祖宗
if (1 == bf || -1 == bf || !RotateTree())
{
break;
}
}
}
}
template <class NodeType>
bool AvlTree<NodeType>::InsertValue(NodeType value)
{
if (NULL == root)
{
root = new AvlNode<NodeType>(value);
return true;
}
if ( false == FindPosition(value))
{
//该值的节点已经存在,不需要重复插入
return true;
}
InsertBalanced(value);
return true;
}
template <class NodeType>
void AvlTree<NodeType>::RemoveNode(AvlNode<NodeType> *node)
{
AvlNode<NodeType> *tempNode = NULL;
//有左右子树
if (NULL != node->lChild && NULL != node->rChild)
{
tempNode = node->lChild;
path[++pathLen] = tempNode;
//找到该node的中序前驱节点
while (NULL != tempNode->rChild)
{
tempNode = tempNode->rChild;
path[++pathLen] = tempNode;
}
node->value = tempNode->value;
//更新中序前驱节点的父节点儿子指针
if (node == path[pathLen - 1])
{
path[pathLen - 1]->lChild = tempNode->lChild;
}
else
{
path[pathLen - 1]->rChild = tempNode->lChild;
}
}
//最多只有一个子树时
else
{
tempNode = node->lChild;
if (NULL == tempNode)
{
tempNode = node->rChild;
}
//删除的是非根节点
if (pathLen > 0)
{
if (path[pathLen - 1]->lChild == node)
{
path[pathLen - 1]->lChild = tempNode;
}
else
{
path[pathLen - 1]->rChild = tempNode;
}
}
else
{
root = tempNode;
}
tempNode = node;
}
RemoveBalanced(node->value);
delete tempNode;
}
template <class NodeType>
bool AvlTree<NodeType>::RemoveValue(NodeType value)
{
pathLen = -1;
AvlNode<NodeType> *node = root;
while (NULL != node)
{
path[++pathLen] = node;
if (value == node->value)
{
RemoveNode(node);
return true;
}
if (node->value < value)
{
node = node->rChild;
}
else
{
node = node->lChild;
}
}
return false;
}
int main()
{
AvlTree<int> test;
int n;
int data;
int operation;
while (true)
{
cout << "Please select operation(0 for insert, 1 for remove, others for exit):";
cin >> operation;
if (0 == operation)
{
cout << "How many number do you want to insert:";
cin >> n;
while (n--)
{
cin >> data;
test.InsertValue(data);
}
}
else if (1 == operation)
{
cout << "How many number do you want to remove:";
cin >> n;
while (n--)
{
cin >> data;
test.RemoveValue(data);
}
}
else
{
break;
}
cout << "Result:" << endl;
test.InfixOutput(test.GetRoot());
}
return 0;
}