AVL树的两个详细实现过程,先转载记录
1. http://www.cnblogs.com/vamei/archive/2013/03/21/2964092.html,
2. http://www.cnblogs.com/daoluanxiaozi/archive/2012/04/26/2471256.html,
看过原理了,下面自己实现
结点AVLNode信息为:
#include <iostream>
using namespace std;
struct AVLNode
{
int height;
int value;
struct AVLNode *parent;
struct AVLNode *lAVLNode;
struct AVLNode *rAVLNode;
AVLNode(): height(0), value(0), parent(NULL), lAVLNode(NULL), rAVLNode(NULL)
{
}
};
AVLTree的声明为:
#include "AVLNode.h"
#define ABS(X) X>0? X:-X
class AVLTree
{
public:
bool midOrder();
bool preOrder();
AVLTree& insert(int value);
AVLTree();
virtual ~AVLTree();
protected:
void midOrder(AVLNode* root);
void preOrder(AVLNode* root);
void RRRotate(AVLNode* pNodeImbalance);
void RLRotate(AVLNode* pNodeImbalance);
void LRRotate(AVLNode* pNodeImbalance);
void LLRotate(AVLNode* pNodeImbalance);
void checkCondition(AVLNode* pNewNode);
AVLNode* root;
};
树的实现部分为:
#include "AVLTree.h"
//
// Construction/Destruction
//
AVLTree::AVLTree()
{
this->root = NULL;
}
AVLTree::~AVLTree()
{
}
AVLTree& AVLTree::insert(int value)
{
bool bCheck = false; //用于标识是否需要检查调整,为1表示需要调整
AVLNode* pNewNode = new AVLNode;
pNewNode->value = value;
AVLNode* pTmp = this->root;
AVLNode* pTmpC = pTmp;
if (NULL == this->root)
{
this->root = pNewNode;
return *this;
}
//找到要插入的位置
while(NULL != pTmp)
{
pTmpC = pTmp;
if (value > pTmp->value)
{
pTmp = pTmp->rAVLNode;
}
else
{
pTmp = pTmp->lAVLNode;
}
}
if (value > pTmpC->value)
{
pTmpC->rAVLNode = pNewNode;
pNewNode->parent = pTmpC;
//如果pNewNode没有兄弟节点,
//则需要通过判断其父节点及其祖宗节点
//是否满足条件以确定是否需要调整
if (NULL == pTmpC->lAVLNode)
{
bCheck = true;
}
}
else
{
pTmpC->lAVLNode = pNewNode;
pNewNode->parent = pTmpC;
if (NULL == pTmpC->rAVLNode)
{
bCheck = true;
}
}
if (bCheck)
{
// checkCondition(pNewNode->parent);
/*这样调用的话,在checkCondition函数的while语句中,处理起来就会简单
*/
checkCondition(pNewNode->parent);
}
return *this;
}
void AVLTree::checkCondition(AVLNode *pNewNodeParent)
{
AVLNode *pTmp = pNewNodeParent;
int balanceFactor = 0;
int lHeight=0, rHeight=0;
int i=0, j=0;
/*
*边计算新插入节点的父节点及其祖先节点的高度
*边判断平衡因子
*/
while((NULL != pTmp) && (ABS(balanceFactor) < 2))
{
lHeight = (NULL == pTmp->lAVLNode) ? 0 : pTmp->lAVLNode->height + 1;
rHeight = (NULL == pTmp->rAVLNode) ? 0 : pTmp->rAVLNode->height + 1;
pTmp->height = lHeight > rHeight ? lHeight : rHeight;
balanceFactor = lHeight - rHeight;
pTmp = pTmp->parent;
}
/*
*此时要么pTmp为空,
*要么balabceFactor为2,这时就需要进行调整了
*且二者不可能同时满足
*/
int x = ABS(balanceFactor);
if (x >= 2)
{
/*
*判断旋转类型,记失衡节点为X节点
*如果X左高,且X->L左高,则为LL
* X->L右高,则为LR
* X右高,且X->R左高, 则为RL
* X->R右高,则为RR
*/
/*
*如果pTmp指向NULL,则失衡节点为root节点
*/
if (NULL == pTmp)
{
pTmp = this->root;
}
else if (balanceFactor > 0)
{
pTmp = pTmp->lAVLNode;
}
else
{
pTmp = pTmp->rAVLNode;
}
//让pTMP指向失衡的节点
if (balanceFactor > 0)
{
pTmp = pTmp->lAVLNode;
i=1;
}
else
{
pTmp = pTmp->rAVLNode;
i=2;
}
lHeight = (NULL == pTmp->lAVLNode) ? 0 : pTmp->lAVLNode->height + 1;
rHeight = (NULL == pTmp->rAVLNode) ? 0 : pTmp->rAVLNode->height + 1;
lHeight > rHeight ? j = 1 : j = 2;
switch(i)
{
case 1:
switch(j)
{
case 1:
LLRotate(pTmp);
break;
case 2:
LRRotate(pTmp);
break;
}
break;
case 2:
switch(j)
{
case 1:
RLRotate(pTmp);
break;
case 2:
RRRotate(pTmp);
break;
}
break;
}//end switch
}//end if
}
void AVLTree::LLRotate(AVLNode *pNodeImbalance)
{
AVLNode *pTmp = pNodeImbalance->rAVLNode;
pNodeImbalance->rAVLNode = pNodeImbalance->parent;
pNodeImbalance->parent = pNodeImbalance->parent->parent;
pNodeImbalance->rAVLNode->parent = pNodeImbalance;
pNodeImbalance->rAVLNode->lAVLNode = pTmp;
if (NULL == pNodeImbalance->parent)
{
this->root = pNodeImbalance;
}
else
{
pNodeImbalance->parent->lAVLNode = pNodeImbalance;
}
/*
*调整节点的高度
*/
int pNImbalaRChildRChildHeigh, pNImbalaRChildLChildHeigh;
pNImbalaRChildLChildHeigh = (NULL == pNodeImbalance->rAVLNode->lAVLNode) ? 0 : pNodeImbalance->rAVLNode->lAVLNode->height + 1;
pNImbalaRChildRChildHeigh = (NULL == pNodeImbalance->rAVLNode->rAVLNode) ? 0 : pNodeImbalance->rAVLNode->rAVLNode->height + 1;
pNodeImbalance->rAVLNode->height = (pNImbalaRChildLChildHeigh > pNImbalaRChildRChildHeigh) ? pNImbalaRChildLChildHeigh : pNImbalaRChildRChildHeigh;
pNodeImbalance->height = pNodeImbalance->lAVLNode->height > pNodeImbalance->rAVLNode->height ?
pNodeImbalance->lAVLNode->height + 1 : pNodeImbalance->rAVLNode->height + 1;
}
void AVLTree::LRRotate(AVLNode *pNodeImbalance)
{
AVLNode* pTmp = pNodeImbalance;
AVLNode* pImbalanceRChild = pNodeImbalance->rAVLNode;
AVLNode* pImbalanceRChildLChild = pNodeImbalance->rAVLNode->lAVLNode;
//左旋转&同时过继pNodeImbalance的右孩子的左孩子
pTmp->parent->lAVLNode = pNodeImbalance;
pImbalanceRChild->parent = pTmp->parent;
pTmp->parent = pImbalanceRChild;
pImbalanceRChild->lAVLNode = pTmp;
//过继pNodeImbalance的右孩子的左孩子
pTmp->rAVLNode = pImbalanceRChildLChild;
if (NULL != pImbalanceRChildLChild)
{
pImbalanceRChildLChild->parent = pTmp;
}
//调整pImbalanceRChild和pTmp的高度
int lHeight, rHeight;
//首先调整pTmp的高度
lHeight = (NULL == pTmp->lAVLNode) ? 0 : pTmp->lAVLNode->height + 1;
rHeight = (NULL == pTmp->rAVLNode) ? 0 : pTmp->rAVLNode->height + 1;
pTmp->height = lHeight > rHeight ? lHeight : rHeight;
//调整pImbalaceRChild的高度
lHeight = pTmp->height + 1;
rHeight = (NULL == pImbalanceRChild->rAVLNode) ? 0 : pImbalanceRChild->rAVLNode->height + 1;
pImbalanceRChild->height = lHeight > rHeight ? lHeight : rHeight;
//右旋转,直接调用RRRoute()
LLRotate(pImbalanceRChild);
}
void AVLTree::RLRotate(AVLNode *pNodeImbalance)
{
AVLNode* pTmp = pNodeImbalance;
AVLNode* pImbalanceLChild = pNodeImbalance->lAVLNode;
AVLNode* pImbalanceLChildRChild = pNodeImbalance->lAVLNode->rAVLNode;
//右上提pImbalanceLChild
pTmp->parent->rAVLNode = pImbalanceLChild;
pImbalanceLChild->parent = pTmp->parent;
pTmp->parent = pImbalanceLChild;
pImbalanceLChild->rAVLNode = pTmp;
//过继pImbalanceLChild的右孩子给pTmp
pTmp->lAVLNode = pImbalanceLChildRChild;
if (NULL != pImbalanceLChildRChild)
{
pImbalanceLChildRChild->parent = pTmp;
}
//调整pImbalanceLChild和pTmp的高度
int lHeight, rHeight;
//首先调整pTmp的高度
lHeight = (NULL == pTmp->lAVLNode) ? 0 : pTmp->lAVLNode->height + 1;
rHeight = (NULL == pTmp->rAVLNode) ? 0 : pTmp->rAVLNode->height + 1;
pTmp->height = lHeight > rHeight ? lHeight : rHeight;
//调整pImbalanceLChild的高度
lHeight = (NULL == pImbalanceLChild->lAVLNode) ? 0 : pImbalanceLChild->lAVLNode->height + 1;
rHeight = pTmp->height + 1;
pImbalanceLChild->height = lHeight > rHeight ? lHeight : rHeight;
RRRotate(pImbalanceLChild);
}
void AVLTree::RRRotate(AVLNode *pNodeImbalance)
{
AVLNode *pTmp = pNodeImbalance->lAVLNode;
pNodeImbalance->lAVLNode = pNodeImbalance->parent;
pNodeImbalance->parent = pNodeImbalance->parent->parent;
pNodeImbalance->lAVLNode->parent = pNodeImbalance;
pNodeImbalance->lAVLNode->rAVLNode = pTmp;
if (NULL == pNodeImbalance->parent)
{
this->root = pNodeImbalance;
}
else
{
pNodeImbalance->parent->rAVLNode = pNodeImbalance;
}
/*
*调整节点高度
*/
int pNodeImbaLChLHeight, pNodeImbaLChRHeight;
pNodeImbaLChLHeight = (NULL == pNodeImbalance->lAVLNode->lAVLNode) ?
0 : pNodeImbalance->lAVLNode->lAVLNode->height + 1;
pNodeImbaLChRHeight = (NULL == pNodeImbalance->lAVLNode->rAVLNode) ?
0 : pNodeImbalance->lAVLNode->rAVLNode->height + 1;
pNodeImbalance->lAVLNode->height = pNodeImbaLChLHeight > pNodeImbaLChRHeight ? pNodeImbaLChLHeight : pNodeImbaLChRHeight;
pNodeImbalance->height = pNodeImbalance->lAVLNode->height > pNodeImbalance->rAVLNode->height ?
pNodeImbalance->lAVLNode->height + 1 : pNodeImbalance->rAVLNode->height + 1;
}
bool AVLTree::preOrder()
{
this->preOrder(this->root);
return true;
}
void AVLTree::preOrder(AVLNode *node)
{
if (NULL != node)
{
printf("key:%d\theight:%d\n", node->value, node->height);
preOrder(node->lAVLNode);
preOrder(node->rAVLNode);
}
}
bool AVLTree::midOrder()
{
this->midOrder(this->root);
return true;
}
void AVLTree::midOrder(AVLNode *node)
{
if (NULL != node)
{
this->midOrder(node->lAVLNode);
printf("key:%d\theight:%d\n", node->value, node->height);
this->midOrder(node->rAVLNode);
}
}
AVLTree还有以下几方面的工作未完成:
- 删除指定值的结点
- 树的清空
- 析构(同清空)
写个main函数,测试一下:
#include "AVLTree.h"
int main()
{
int value[] = {2,3,4,6,5,8,9,7,12,15,20,18};
int valueCount = 12, i;
AVLTree avltree;
for (i=0; i<valueCount; ++i)
{
avltree.insert(value[i]);
}
printf("前序:\n");
avltree.preOrder();
printf("\n中序:\n");
avltree.midOrder();
return 0;
}
测试结果:
自己画了一下,结果正确
1. 首先插入2、3、4,插入4之后,key为2的结点失衡,此时以key为3的结点为轴,做RR旋转
2. 插入6、5,插入5之后,导致key为4的结点失衡,以key为6的结点为轴,做RL旋转
3. 继续插入8,此时key为3的结点失衡,以key为5的结点为轴,做RR旋转
4. 继续插入9,此时key为6的结点失衡,以key为8的结点为轴,做RR旋转
5. 继续插入7、12、15,此时key为9的结点失衡,以key为12的结点为轴,做RR旋转
6. 继续插入20,此时key为5的结点失衡,以key为8的结点为轴,做RR旋转
7.继续插入18,此时key为15的结点失衡,以key为20的结点为轴,做RL旋转
至此,AVL树建立成功
(P.S.在上述过程中,貌似只用了RR和RL旋转,没有使用LL和LR旋转)
再使用另外一组数据测试,
又重新写了一组数:
int value[] = {9,7,4,2,3,6,5,8,12,1,15,20,18};
int valueCount = 13, i;
测试结果为:
测试结果也正确
至此,建树的过程,应该没有错误。
后续再添加结点的删除及树的清空工作