《数据结构实战》创建一颗平衡二叉树

来源:互联网 发布:重庆优化 编辑:程序博客网 时间:2024/05/18 15:55

平衡二叉树是一种防止搜索二叉树退化成链表的树,平衡二叉树的左右子树的高度相差不超过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);elseDoubleRotateLeftRight(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);elseDoubleRotateRightLeft(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);elseDoubleRotateLeftRight(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);elseDoubleRotateRightLeft(pNode); // 右走情况}}else{RemoveNode(pNode->lTree, nValue); // 左子树查找if (2 == GetHigh(pNode->lTree) - GetHigh(pNode->rTree)){if (GetHigh(pNode->lTree) > GetHigh(pNode->rTree)) // 左左情况SignelRotateLeftLeft(pNode);elseDoubleRotateLeftRight(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;}