平衡二叉树是一种防止搜索二叉树退化成链表的树,平衡二叉树的左右子树的高度相差不超过1,因此在插入及删除时有必要重新旋转树,以达到是一颗平衡树。为简单起见,仅使用int型数据,并且在有相同节点时,更新nCount的值。代码如下:
#ifndef __CBALANCETREE__H
#define __CBALANCETREE__H
#include <iostream>
struct TreeNode
{
int nData; // 节点的值
TreeNode* lTree; // 左节点
TreeNode* rTree; // 右节点
int nHigh; // 树的高度
int nCount; // 相同的值的次数
TreeNode()
{
nData = 0;
lTree = NULL;
rTree = NULL;
nHigh = 0;
nCount = 0;
}
};
inline int GetHigh(TreeNode* pNode) // 获取节点高度 空节点为-1
{
if (pNode)
return pNode->nHigh;
return -1;
}
inline int Max(int a, int b)
{
return a > b ? a : b;
}
class CBalanceTree // 平衡二叉树
{
public:
CBalanceTree();
~CBalanceTree();
public:
bool InsertNode(int nValue); // 插入节点
bool RemoveNode(int nValue); // 删除节点
bool FindData(int nValue); // 查找是否有该节点
void BreadthTraversal(); // 层序遍历
void MiddleTraversal(); // 中序遍历 根左右
private:
bool InsertNode(TreeNode*& pNode, int nValue);
bool RemoveNode(TreeNode*& pNode, int nValue);
bool FindNode(TreeNode* pNode, int nValue);
void SignelRotateLeftLeft(TreeNode*& pNode); // 左左情况 单旋转
void DoubleRotateLeftRight(TreeNode*& pNode); // 左右情况 双旋转
void SignelRotateRightRight(TreeNode*& pNode); // 右右情况 单旋转
void DoubleRotateRightLeft(TreeNode*& pNode); // 右左情况 双旋转
private:
void MiddleTraversal(TreeNode* pNode);
void DeleteNode(TreeNode*& pNode);
private:
TreeNode* m_pRoot;
};
#endif
实现文件:
#include "BalanceTree.h"
#include <queue>
CBalanceTree::CBalanceTree()
{
m_pRoot = NULL;
}
CBalanceTree::~CBalanceTree()
{
DeleteNode(m_pRoot);
}
bool CBalanceTree::InsertNode(int nValue)
{
return InsertNode(m_pRoot, nValue);
}
bool CBalanceTree::InsertNode(TreeNode*& pNode, int nValue)
{
if (!pNode)
{
pNode = new TreeNode;
pNode->nData = nValue;
return true;
}
if (nValue < pNode->nData) // 左子树插入
{
InsertNode(pNode->lTree, nValue);
if (2 == GetHigh(pNode->lTree) - GetHigh(pNode->rTree)) // 高度相差2 不平衡
{
if (GetHigh(pNode->lTree) > GetHigh(pNode->rTree)) // 左左情况 单旋转
SignelRotateLeftLeft(pNode);
else
DoubleRotateLeftRight(pNode); // 左右情况 双旋转
}
}
else if (nValue > pNode->nData) // 右子树插入
{
InsertNode(pNode->rTree, nValue);
if (2 == GetHigh(pNode->rTree) - GetHigh(pNode->lTree))
{
if (GetHigh(pNode->rTree) > GetHigh(pNode->lTree)) // 右右情况
SignelRotateRightRight(pNode);
else
DoubleRotateRightLeft(pNode); // 右左情况
}
}
else // 相同
pNode->nCount += 1;
// 更新树的高度
pNode->nHigh = Max(GetHigh(pNode->lTree), GetHigh(pNode->rTree)) + 1;
return true;
}
void CBalanceTree::SignelRotateLeftLeft(TreeNode*& pK1)
{
TreeNode* pK2 = pK1->lTree;
pK1->lTree = pK2->rTree;
int nHigh = GetHigh(pK2->rTree);
pK2->rTree = pK1;
// 更新树的高度
pK1->nHigh = Max(nHigh,GetHigh(pK1->rTree)) + 1;
pK2->nHigh = Max(GetHigh(pK2->lTree), GetHigh(pK2->rTree)) + 1;
pK1 = pK2;
}
void CBalanceTree::SignelRotateRightRight(TreeNode*& pK1)
{
TreeNode* pK2 = pK1->rTree;
int nHigh = GetHigh(pK2->lTree);
pK1->rTree = pK2->lTree;
pK2->lTree = pK1;
// 更新树的高度
pK1->nHigh = Max(nHigh, GetHigh(pK1->lTree)) + 1;
pK2->nHigh = Max(GetHigh(pK2->lTree), GetHigh(pK2->rTree)) + 1;
pK1 = pK2;
}
void CBalanceTree::DoubleRotateLeftRight(TreeNode*& pNode) // 左右情况
{
SignelRotateRightRight(pNode->lTree); // 局部是右
SignelRotateLeftLeft(pNode);
}
void CBalanceTree::DoubleRotateRightLeft(TreeNode*& pNode) // 右左情况
{
SignelRotateLeftLeft(pNode->rTree); // 局部是左
SignelRotateRightRight(pNode);
}
bool CBalanceTree::RemoveNode(int nValue)
{
return RemoveNode(m_pRoot, nValue);
}
bool CBalanceTree::RemoveNode(TreeNode*& pNode, int nValue)
{
if (!pNode)
return false; // 没有该节点
if (pNode->nData == nValue)
{
if (pNode->nCount > 0)
{
pNode->nCount -= 1;
return true;
}
else // 删除
{
if (pNode->lTree && pNode->rTree) // 有左右子树
{
// 找到右子树中最小的 即最左 替换该节点
TreeNode* pTemp = pNode->rTree;
while (pTemp->lTree)
pTemp = pTemp->lTree;
pNode->nCount = pTemp->nCount;
pNode->nData = pTemp->nData;
RemoveNode(pNode->rTree, pTemp->nData); // 删除该节点
if (2 == GetHigh(pNode->lTree) - GetHigh(pNode->rTree))
{
if (GetHigh(pNode->lTree) > GetHigh(pNode->rTree)) // 左左情况
SignelRotateLeftLeft(pNode);
else
DoubleRotateLeftRight(pNode);
}
}
else // 仅有一个节点
{
if (pNode->rTree) // 有右节点
{
pNode->nData = pNode->rTree->nData;
pNode->nCount = pNode->rTree->nCount;
delete pNode->rTree;
pNode->rTree = NULL;
}
else if (pNode->lTree) // 有左节点
{
pNode->nData = pNode->lTree->nData;
pNode->nCount = pNode->lTree->nCount;
delete pNode->lTree;
pNode->lTree = NULL;
}
else
{
delete pNode;
pNode = NULL;
return true;
}
}
}
}
else if (pNode->nData < nValue) // 右子树查找
{
RemoveNode(pNode->rTree, nValue);
if (2 == GetHigh(pNode->rTree) - GetHigh(pNode->lTree))
{
if (GetHigh(pNode->rTree) > GetHigh(pNode->lTree)) // 右右情况 单旋转
SignelRotateRightRight(pNode);
else
DoubleRotateRightLeft(pNode); // 右走情况
}
}
else
{
RemoveNode(pNode->lTree, nValue); // 左子树查找
if (2 == GetHigh(pNode->lTree) - GetHigh(pNode->rTree))
{
if (GetHigh(pNode->lTree) > GetHigh(pNode->rTree)) // 左左情况
SignelRotateLeftLeft(pNode);
else
DoubleRotateLeftRight(pNode); // 左右情况
}
}
pNode->nHigh = Max(GetHigh(pNode->lTree), GetHigh(pNode->rTree)) + 1;
return true;
}
bool CBalanceTree::FindData(int nValue)
{
return FindNode(m_pRoot, nValue);
}
bool CBalanceTree::FindNode(TreeNode* pNode, int nValue)
{
if (!pNode)
return false;
if (nValue < pNode->lTree->nData) // 左子树查找
FindNode(pNode->lTree, nValue);
else if (nValue > pNode->rTree->nData)
FindNode(pNode->rTree, nValue);
else // 找到
return true;
}
void CBalanceTree::BreadthTraversal() // 层序遍历
{
if (!m_pRoot)
return;
std::queue<TreeNode*> queueTreeNode;
queueTreeNode.push(m_pRoot);
while (!queueTreeNode.empty())
{
TreeNode* pNode = queueTreeNode.front();
std::cout << pNode->nData << "\t";
queueTreeNode.pop();
if (pNode->lTree)
queueTreeNode.push(pNode->lTree);
if (pNode->rTree)
queueTreeNode.push(pNode->rTree);
}
}
void CBalanceTree::MiddleTraversal() // 中序遍历
{
MiddleTraversal(m_pRoot);
}
void CBalanceTree::MiddleTraversal(TreeNode* pNode)
{
if (!pNode)
return;
std::cout << pNode->nData << "\t";
MiddleTraversal(pNode->lTree);
MiddleTraversal(pNode->rTree);
}
void CBalanceTree::DeleteNode(TreeNode*& pNode)
{
if (!pNode)
return;
DeleteNode(pNode->lTree);
DeleteNode(pNode->rTree);
delete pNode;
pNode = NULL;
}
测试代码:
#include "BalanceTree.h"
int main()
{
CBalanceTree balanceTree;
balanceTree.InsertNode(15);
balanceTree.InsertNode(10);
balanceTree.InsertNode(8);
balanceTree.InsertNode(17);
balanceTree.InsertNode(11);
balanceTree.InsertNode(16);
balanceTree.InsertNode(7);
balanceTree.InsertNode(9);
balanceTree.RemoveNode(10);
balanceTree.BreadthTraversal();
return 0;
}