平衡二叉树是一种防止搜索二叉树退化成链表的树,平衡二叉树的左右子树的高度相差不超过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; }