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;
}