[学习笔记]AVL平衡二叉树

AVL平衡二叉树的实现:

#include "stdafx.h"
#include <iostream>
class CAVLTree
{
public:
	CAVLTree() :m_pRoot(nullptr){};
	~CAVLTree(){};
public:
	typedef struct _NODE
	{
		int nData;
		_NODE* pLeft;
		_NODE* pRight;
	}NODE, *pNODE;
public:
	//向二叉树中添加一个数据
	bool Insert(int nEle, int& nError);
	bool Insert(
		int nEle,			//插入的数据     
		pNODE& pNode,		//要插入的节点
		int& nError			//错误码
		);
	//从二叉树中删除一个数据
	bool Delete(int nEle, int& nError);
	bool Delete(
		int nEle,			//要被删掉的数据
		pNODE& pTree,		//要删除节点的子树
		int& nError			//错误码
		);
	//判断一棵树是否为空
	bool IsEmpty(){ return m_pRoot ? false : true; }
	//获取一个子树的高度
	int GetHeight(pNODE pTree);
	//获取最大值
	bool GetMax(pNODE pTree, int& nMax);
	//获取最小值
	bool GetMin(pNODE pTree, int& nMin);
	//前序遍历
	void PreOrderTraverse();
	void PreOrderTraverse(pNODE pNode);
	//中序遍历
	void InOrderTraverse();
	void InOrderTraverse(pNODE pNode);
	//后序遍历
	void PostOrderTraverse();
	void PostOrderTraverse(pNODE pNode);	
	//左旋和右旋
	bool SingleL(pNODE& pNode);
	bool SingleR(pNODE& pNode);
	bool DoubleLR(pNODE& pNode);
	bool DoubleRL(pNODE& pNode);
private:
	pNODE m_pRoot;	//根节点指针
};
//************************************************************
// 函数名称:	Insert
// 函数说明:	向二叉树中添加一个数据
// 作	者:	Dylan
// 时	间:	2015/08/25
// 参	数:	int nEle
// 参	数:	int & nError
// 返 回	值:	bool
//************************************************************
bool CAVLTree::Insert(int nEle, int& nError)
{
	if (Insert(nEle, m_pRoot, nError))
	{
		return true;
	}
	return false;
}
bool CAVLTree::Insert(int nEle, pNODE& pNode, int& nError)
{
	bool bSuccess = false;
	//1.判断是否是要插入的节点
	if (pNode == nullptr)
	{
		pNode = new NODE;
		pNode->pLeft = nullptr;
		pNode->pRight = nullptr;
		pNode->nData = nEle;
		return true;
	}
	//2.判断要插入的数据和当前根节点比较大小
	if (nEle>pNode->nData)
	{
		bSuccess = Insert(nEle, pNode->pRight, nError);
	}
	else if (nEle<pNode->nData)
	{
		bSuccess = Insert(nEle, pNode->pLeft, nError);
	}
	else
	{
		return false;
	}
	//AVL
	//3.判断一下经历了删除之后,本节点是否平衡
	int nLHight = GetHeight(pNode->pLeft);
	int nRHight = GetHeight(pNode->pRight);
	int nSub = nLHight - nRHight;
	//3.1如果左边高
	if (nSub == 2)
	{
		//3.1.1右旋
		nLHight = GetHeight(pNode->pLeft->pLeft);
		nRHight = GetHeight(pNode->pLeft->pRight);
		if (nLHight >= nRHight)
		{
			SingleR(pNode);
		}
		//3.1.2左右旋
		else
		{
			DoubleLR(pNode);
		}
	}
	//3.2如果右边高
	else if (nSub == -2)
	{
		//3.2.1左旋
		nLHight = GetHeight(pNode->pRight->pLeft);
		nRHight = GetHeight(pNode->pRight->pRight);
		if (nLHight <= nRHight)
		{
			SingleL(pNode);
		}
		//3.2.2右左旋
		else
		{
			DoubleRL(pNode);
		}
	}
	return true;
}
//************************************************************
// 函数名称:	Delete
// 函数说明:	从二叉树中删除一个数据
// 作	者:	Dylan
// 时	间:	2015/08/26
// 参	数:	int nEle
// 参	数:	int & nError
// 返 回	值:	bool
//************************************************************
bool CAVLTree::Delete(int nEle, int& nError)
{
	if (Delete(nEle, m_pRoot, nError))
	{
		return true;
	}
	return false;
}
bool CAVLTree::Delete(int nEle, pNODE& pTree, int& nError)
{
	bool bSuccess = false;
	//1.判断节点是否为空
	if (pTree == NULL)
	{
		return false;
	}
	//2.判断要删除的数据比当前子树的根节点大还是小
	if (nEle>pTree->nData)
	{
		bSuccess = Delete(nEle, pTree->pRight, nError);
	}
	else if (nEle<pTree->nData)
	{
		bSuccess = Delete(nEle, pTree->pLeft, nError);
	}
	//3.判断要删除的数据和当前子树根节点一样大,应该删除
	else
	{
		//3.1要删除的点是一个叶子节点
		if (pTree->pLeft == nullptr&&pTree->pRight == nullptr)
		{
			delete pTree;
			pTree = nullptr;
			return true;
		}
		//3.2要删除的点是一个树干
		//3.2.1分别获取此节点的左子树高和有子树高
		int nLeftHeight = 0;
		int nRightHeight = 0;
		nLeftHeight = GetHeight(pTree->pLeft);
		nRightHeight = GetHeight(pTree->pRight);
		//3.2.2判断一下,这两棵树谁高
		if (nLeftHeight>nRightHeight)
		{
			int nMax = 0;
			GetMax(pTree->pLeft, nMax);
			pTree->nData = nMax;
			bSuccess = Delete(nMax, pTree->pLeft, nError);
		}
		else
		{
			int nMin = 0;
			GetMin(pTree->pRight, nMin);
			pTree->nData = nMin;
			bSuccess = Delete(nMin, pTree->pRight, nError);
		}
	}
	if (bSuccess==false)
	{
		return bSuccess;
	}
	//AVL
	//5.判断一下经历了删除之后,本节点是否平衡
	int nLHight = GetHeight(pTree->pLeft);
	int nRHight = GetHeight(pTree->pRight);
	int nSub = nLHight - nRHight;
	//5.1如果左边高
	if (nSub == 2)
	{
		//5.1.1右旋
		nLHight = GetHeight(pTree->pLeft->pLeft);
		nRHight = GetHeight(pTree->pLeft->pRight);
		if (nLHight >= nRHight)
		{
			SingleR(pTree);
		}
		//5.1.2左右旋
		else
		{
			DoubleLR(pTree);
		}
	}
	//5.2如果右边高
	else if(nSub == -2)
	{
		//5.2.1左旋
		nLHight = GetHeight(pTree->pRight->pLeft);
		nRHight = GetHeight(pTree->pRight->pRight);
		if (nLHight <= nRHight)
		{
			SingleL(pTree);
		}
		//5.2.2右左旋
		else
		{
			DoubleRL(pTree);
		}
	}
	return true;
}
//************************************************************
// 函数名称:	GetHeight
// 函数说明:	获取一个子树的高度
// 作	者:	Dylan
// 时	间:	2015/08/26
// 参	数:	pNODE pTree
// 返 回	值:	int
//************************************************************
int CAVLTree::GetHeight(pNODE pTree)
{
	if (pTree == nullptr)
	{
		return 0;
	}
	int nLeftHeight = GetHeight(pTree->pLeft);
	int nRightHeight = GetHeight(pTree->pRight);
	return (nLeftHeight > nRightHeight ? nLeftHeight : nRightHeight) + 1;
}
//************************************************************
// 函数名称:	GetMax
// 函数说明:	获取最大值
// 作	者:	Dylan
// 时	间:	2015/08/26
// 参	数:	pNODE pTree
// 参	数:	int & nMax
// 返 回	值:	bool
//************************************************************
bool CAVLTree::GetMax(pNODE pTree, int& nMax)
{
	if (pTree == nullptr)
	{
		return false;
	}
	while (pTree)
	{
		nMax = pTree->nData;
		pTree = pTree->pRight;
	}
	return true;
}
//************************************************************
// 函数名称:	GetMin
// 函数说明:	获取最小值
// 作	者:	Dylan
// 时	间:	2015/08/26
// 参	数:	pNODE pTree
// 参	数:	int & nMin
// 返 回	值:	bool
//************************************************************
bool CAVLTree::GetMin(pNODE pTree, int& nMin)
{
	if (pTree == nullptr)
	{
		return false;
	}
	while (pTree)
	{
		nMin = pTree->nData;
		pTree = pTree->pLeft;
	}
	return true;
}
//************************************************************
// 函数名称:	PreOrderTraverse
// 函数说明:	前序遍历
// 作	者:	Dylan
// 时	间:	2015/08/25
// 返 回	值:	void
//************************************************************
void CAVLTree::PreOrderTraverse()
{
	PreOrderTraverse(m_pRoot);
	std::cout << std::endl;
}

void CAVLTree::PreOrderTraverse(pNODE pNode)
{
	if (pNode == nullptr)
	{
		return;
	}
	std::cout << pNode->nData << " ";
	PreOrderTraverse(pNode->pLeft);
	PreOrderTraverse(pNode->pRight);
}
//************************************************************
// 函数名称:	InOrderTraverse
// 函数说明:	中序遍历
// 作	者:	Dylan
// 时	间:	2015/08/25
// 返 回	值:	void
//************************************************************
void CAVLTree::InOrderTraverse()
{
	InOrderTraverse(m_pRoot);
	std::cout << std::endl;
}
void CAVLTree::InOrderTraverse(pNODE pNode)
{
	{
		if (pNode == nullptr)
		{
			return;
		}
		InOrderTraverse(pNode->pLeft);
		std::cout << pNode->nData << " ";
		InOrderTraverse(pNode->pRight);
	}
}
//************************************************************
// 函数名称:	PostOrderTraverse
// 函数说明:	后序遍历
// 作	者:	Dylan
// 时	间:	2015/08/25
// 返 回	值:	void
//************************************************************
void CAVLTree::PostOrderTraverse()
{
	PostOrderTraverse(m_pRoot);
	std::cout << std::endl;
}
void CAVLTree::PostOrderTraverse(pNODE pNode)
{
	{
		if (pNode == nullptr)
		{
			return;
		}
		PostOrderTraverse(pNode->pLeft);
		PostOrderTraverse(pNode->pRight);
		std::cout << pNode->nData << " ";
	}
}
//************************************************************
// 函数名称:	SingleL              K2                K1  
// 函数说明:	左单旋                 \              /  \
// 作	者:	Dylan                   K1     =>    K2   N
// 时	间:	2015/08/26               \
// 参	数:	pNODE & pNode             N
// 返 回	值:	bool
//************************************************************
bool CAVLTree::SingleL(pNODE& pNode)
{
	pNODE k2 = pNode;
	pNODE k1 = pNode->pRight;
	k2->pRight = k1->pLeft;
	k1->pLeft = k2;
	pNode = k1;
	return true;
}
//************************************************************
// 函数名称:	SingleR                  K2            K1      
// 函数说明:	右单旋                   /            / \
// 作	者:	Dylan                   K1     =>    N   K2 
// 时	间:	2015/08/26             /
// 参	数:	pNODE & pNode         N
// 返 回	值:	bool
//************************************************************
bool CAVLTree::SingleR(pNODE& pNode)
{
	pNODE k2 = pNode;
	pNODE k1 = pNode->pLeft;
	k2->pLeft = k1->pRight;
	k1->pRight = k2;
	pNode = k1;
	return true;
}
//************************************************************
// 函数名称:	DoubleLR          K2          K2         N
// 函数说明:	左右双旋          /           /         / \
// 作	者:	Dylan            K1    =>    N    =>  K1   K2
// 时	间:	2015/08/26         \        /
// 参	数:	pNODE & pNode       N      K1
// 返 回	值:	bool
//************************************************************
bool CAVLTree::DoubleLR(pNODE& pNode)
{
	SingleL(pNode->pLeft);
	SingleR(pNode);
	return true;
}
//************************************************************
// 函数名称:	DoubleRL         K2        K2              N
// 函数说明:	右左双旋           \         \            / \
// 作	者:	Dylan               K1 =>     N    =>   K2   K1
// 时	间:	2015/08/26         /           \
// 参	数:	pNODE & pNode     N             K1
// 返 回	值:	bool
//************************************************************
bool CAVLTree::DoubleRL(pNODE& pNode)
{
	SingleR(m_pRoot->pRight);
	SingleL(pNode);
	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int nError = 0;
	CAVLTree obj;
	for (int i = 1; i < 100;i+=5)
	{
		obj.Insert(i, nError);
	}
	//下个断点 观察根节点是否有左右子树,若有,则表明可以进行平衡插入。
	obj.PreOrderTraverse();
	obj.InOrderTraverse();
	obj.PostOrderTraverse();

	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值