AVL树

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还有以下几方面的工作未完成:

  1. 删除指定值的结点
  2. 树的清空
  3. 析构(同清空)

写个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;
测试结果为:

测试结果也正确

至此,建树的过程,应该没有错误。

后续再添加结点的删除及树的清空工作


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值