代码:
/******************************************************************** created: 2008/06/11 filename: BalancedTree.h author: happymouse version: v1.0.0.0 *********************************************************************/ #pragma once #include <cassert> // Child node balanced status enum EnumBalancedStatus { LeanToLeft, Balanced, LeanToRight }; // Balanced tree template class template<typename T> class CBalancedTree { private: // Data T m_data; // Left child tree CBalancedTree<T> *m_pLeftChild; // Right child tree CBalancedTree<T> *m_pRightChild; // Current balanced status EnumBalancedStatus m_balancedStatus; public: // Constructor CBalancedTree() :m_pLeftChild(NULL), m_pRightChild(NULL), m_balancedStatus(Balanced) { } // Constructor CBalancedTree(const T& data) :m_pLeftChild(NULL), m_pRightChild(NULL), m_balancedStatus(Balanced) { m_data = data; } // Destructor virtual ~CBalancedTree() { if (NULL != m_pLeftChild) { delete m_pLeftChild; } if (NULL != m_pRightChild) { delete m_pRightChild; } } // Get left child pointer CBalancedTree<T> * GetLeftChild() { return m_pLeftChild; } // Get right child pointer CBalancedTree<T> * GetRightChild() { return m_pRightChild; } // Set data void SetData(const T& data) { m_data = data; } // Get data T& GetData() { return m_data; } // Rotate to left void LeftRotate() { // Swap the data of right child T _swapData = m_data; m_data = m_pRightChild->m_data; m_pRightChild->m_data = _swapData; // Left rotate CBalancedTree<T> *_swapTree = m_pRightChild; m_pRightChild = m_pRightChild->m_pRightChild; _swapTree->m_pRightChild = _swapTree->m_pLeftChild; _swapTree->m_pLeftChild = m_pLeftChild; m_pLeftChild = _swapTree; } // Rotate to right void RightRotate() { // Swap the data of left child T _swapData = m_data; m_data = m_pLeftChild->m_data; m_pLeftChild->m_data = _swapData; // Right rotate CBalancedTree<T> *_swapTree = m_pLeftChild; m_pLeftChild = m_pLeftChild->m_pLeftChild; _swapTree->m_pLeftChild = _swapTree->m_pRightChild; _swapTree->m_pRightChild = m_pRightChild; m_pRightChild = _swapTree; } // Insert a data into tree. If depth is add return true bool Insert(const T& data) { bool _fAppend = false; if (data == m_data) { return _fAppend; } if (data < m_data)// Insert into left child { if (NULL == m_pLeftChild)// Left child depth append { m_pLeftChild = new CBalancedTree<T>(data); _fAppend = true; } else// Insert into child of left child { _fAppend = m_pLeftChild->Insert(data); } if (_fAppend) { _fAppend = false; switch(m_balancedStatus) { case LeanToRight:// Right child has data m_balancedStatus = Balanced; break; case Balanced:// Current depth is append m_balancedStatus = LeanToLeft; _fAppend = true; break; case LeanToLeft:// Must be balaced of current node if (m_pLeftChild->m_balancedStatus == LeanToLeft)// Right rotate { RightRotate(); m_pRightChild->m_balancedStatus = Balanced; break; } else if (m_pLeftChild->m_balancedStatus == LeanToRight) { // Left rotate and Right rotate m_pLeftChild->LeftRotate(); RightRotate(); if(NULL == m_pLeftChild->m_pRightChild) { break; } switch (m_pLeftChild->m_pRightChild->m_balancedStatus) { case LeanToRight: m_pLeftChild->m_balancedStatus = LeanToLeft; m_pRightChild->m_balancedStatus = Balanced; break; case Balanced: m_pLeftChild->m_balancedStatus = Balanced; m_pRightChild->m_balancedStatus = Balanced; break; case LeanToLeft: m_pLeftChild->m_balancedStatus = Balanced; m_pRightChild->m_balancedStatus = LeanToRight; break; } } m_balancedStatus = Balanced; break; } } } else// Insert into right child { if (NULL == m_pRightChild)// Right child depth append { m_pRightChild = new CBalancedTree<T>(data); _fAppend = true; } else// Insert into child of right child { _fAppend = m_pRightChild->Insert(data); } if (_fAppend)// Right node depth append { _fAppend = false; switch(m_balancedStatus) { case LeanToLeft:// Left child has data m_balancedStatus = Balanced; break; case Balanced:// Current depth is append m_balancedStatus = LeanToRight; _fAppend = true; break; case LeanToRight:// Must be balaced of current node if (m_pRightChild->m_balancedStatus == LeanToRight)// Left rotate { LeftRotate(); m_pLeftChild->m_balancedStatus = Balanced; break; } else if (m_pRightChild->m_balancedStatus == LeanToLeft) { // Right rotate and Left rotate m_pRightChild->RightRotate(); LeftRotate(); if (NULL == m_pRightChild->m_pLeftChild) { break; } switch (m_pRightChild->m_pLeftChild->m_balancedStatus) { case LeanToRight: m_pLeftChild->m_balancedStatus = LeanToLeft; m_pRightChild->m_balancedStatus = Balanced; break; case Balanced: m_pLeftChild->m_balancedStatus = Balanced; m_pRightChild->m_balancedStatus = Balanced; break; case LeanToLeft: m_pLeftChild->m_balancedStatus = Balanced; m_pRightChild->m_balancedStatus = LeanToRight; break; } } m_balancedStatus = Balanced; break; } } } return _fAppend; } // If the balanced tree. if sucessed return the depth of tree. // failed return -1 int IsBalanced() { int _nLeftDepth = 0, _nRightDepth = 0; if (NULL != m_pLeftChild) { _nLeftDepth = m_pLeftChild->IsBalanced();// Get left child tree depth } if (NULL != m_pRightChild) { _nRightDepth = m_pRightChild->IsBalanced();// Get right child tree depth } if (-1 == _nLeftDepth || -1 == _nRightDepth || abs(_nLeftDepth - _nRightDepth) > 1)// |ldepth - rdepth| > 1 { return -1; } else if (_nLeftDepth >= _nRightDepth) { return _nLeftDepth + 1;// return left child depth } else { return _nRightDepth + 1;// return right child depth } } // Make a tree by a data array static void MakeTree(T *pData, int nSize, CBalancedTree<T>& out) { assert(nSize > 0); out.SetData(pData[0]); for (int i = 1; i <= nSize; i++) { out.Insert(pData[i]); } } };
平衡树特点:
1.根的左子树和右子树深度差最多为1。
2.根的左子树和右子树都是平衡树。
3.平衡树中不允许出现重复数据。
以下为测试代码:
代码:
int _aryValue1[] = { 1, 2, 3, 4, 5, 6, 7 }; AVL avl1, avl2; AVL::MakeTree(_aryValue1, sizeof(_aryValue1) / sizeof(int), avl1); cout << (avl1.IsBalanced() >= 0? "avl1是平衡树!": "avl1不是平衡树!") << endl; int _aryValue2[] = { 50, 30, 80, 20, 40 }; AVL::MakeTree(_aryValue2, sizeof(_aryValue2) / sizeof(int), avl2); cout << (avl2.IsBalanced() >= 0? "avl2是平衡树!": "avl2不是平衡树!") << endl;