AVL树的模板实现
2016-01-13 12:02
316 查看
测试程序
/// @file exam_x_x.cpp /// @brief exam_2 /** * 编写表达式2叉树(前序,中序,后序)的非递归实现 提示 : 用栈实现, 模拟的方法: 先用递归实现, 单步跟一遍, 看栈上数据的变化, 再用栈模拟. */ #include <iostream> #include <limits> #include "LsTree.h" using namespace std; #define LINE "----------------------------------------------------------------------" void clear_cin(); void fnTestAvl(); ///< 自定义插入结点 void fnTestAvlInsert(); ///< 自动插入有序结点 void fnTestAvlRemove(); ///< test case : remove node void fnTestAvlRemoveRoot(); void fnTestAvlRemoveNoAnyChild(); void fnTestAvlRemoveOneChild(); void fnTestAvlRemoveTwoChild(); bool fnPrintNode_AsCharValue(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt); bool fnPrintNode_Basic(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt); bool fnPrintNode_Detail(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt); int main(int argc, char** argv, char** envp) { // fnTestAvlRemove(); fnTestAvlInsert(); // fnTestAvl(); /** run result tree.printTree_DLR: - + A / * B - C D - E F G tree.printTree_DLR_ex: - + A / * B - C D - E F G tree.printTree_LDR: A + B * C - D / E - F - G tree.printTree_LDR_ex: A + B * C - D / E - F - G tree.printTree_LRD: A B C D - * E F - / + G - tree.printTree_LRD_ex: A B C D - * E F - / + G - */ cout << "END, press any key to quit" << endl; clear_cin(); getchar(); return 0; } void fnTestAvlRemove() { fnTestAvlRemoveTwoChild(); // fnTestAvlRemoveOneChild(); // fnTestAvlRemoveNoAnyChild(); // fnTestAvlRemoveRoot(); } void fnTestAvlRemoveTwoChild() { CAvl<char> tree; /// 删除结点 : 2个孩子 tree.insert(100); tree.insert(80); tree.insert(90); tree.insert(70); tree.insert(75); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); tree.remove(80); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); /// 如果中序遍历看到的节点值是有序的, 就是有序二叉树 /** run result ---------------------------------------------------------------------- [00323EB0][L3:70] [00323E00][00000000][00323F08] [00323F08][L4:75] [00323EB0][00000000][00000000] [00323E00][L2:80] [00323DA8][00323EB0][00323E58] [00323E58][L3:90] [00323E00][00000000][00000000] [00323DA8][L1:100] [00000000][00323E00][00000000] ---------------------------------------------------------------------- [00323EB0][L3:70] [00323E58][00000000][00323F08] [00323F08][L4:75] [00323EB0][00000000][00000000] [00323E58][L2:90] [00323DA8][00323EB0][00000000] [00323DA8][L1:100] [00000000][00323E58][00000000] */ } void fnTestAvlRemoveOneChild() { CAvl<char> tree; /// 删除结点 : 一个孩子 tree.insert(100); tree.insert(80); tree.insert(70); tree.insert(75); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); tree.remove(80); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); /** ---------------------------------------------------------------------- [00030FD8][L3:70] [00030F80][00000000][00031030] [00031030][L4:75] [00030FD8][00000000][00000000] [00030F80][L2:80] [00033DA8][00030FD8][00000000] [00033DA8][L1:100] [00000000][00030F80][00000000] ---------------------------------------------------------------------- [00030FD8][L3:70] [00033DA8][00000000][00031030] [00031030][L4:75] [00030FD8][00000000][00000000] [00033DA8][L1:100] [00000000][00030FD8][00000000] */ } void fnTestAvlRemoveNoAnyChild() { CAvl<char> tree; /// 删除叶子 : 非根结点 tree.insert(100); tree.insert(80); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); tree.remove(80); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); } void fnTestAvlRemoveRoot() { CAvl<char> tree; /// 删除叶子 : 根结点 tree.insert(100); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); tree.remove(100); printf("%s\n", LINE); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail); } void fnTestAvlInsert() { int i = 0; int iOffset = 0; // CAvl tree; CAvl<char> tree1; //---------------------------------------------------------------------- // 建立树 //---------------------------------------------------------------------- // for (i = 10; i > 0; i--) { // /// 当插入数据时, 可以测试到右旋 // /// 当tree析构时, 可以测试到左旋, 左双旋 // tree.insert(i); // } // for (i = 0; i < 10; i++) { // /// 当插入数据时, 可以测试到左旋 // tree1.insert(i); // } /// 测试右双旋 tree1.insert(6); tree1.insert(10); tree1.insert(8); ///< 测试右双旋 tree1.insert(12); tree1.insert(11); tree1.remove(11); ///< 测试删除一个节点带2个孩子 //---------------------------------------------------------------------- // 遍历树 - 中序打印 //---------------------------------------------------------------------- // printf("%s\n", LINE); // printf("tree.TraverseLDR:\n"); // tree.TraverseLDR(tree.getRootNode(), &fnPrintNode_Basic); ///< 非递归实现 // printf("\n"); } void fnTestAvl() { //---------------------------------------------------------------------- // 建立树 //---------------------------------------------------------------------- // A + B*(C-D)/(E-F) - G CAvl<char> tree; CAvlNode<char>* pRootNode = NULL; CAvlNode<char>* pNodeCur = NULL; CAvlNode<char>* pNodeTmp1 = NULL; CAvlNode<char>* pNodeTmp2 = NULL; CAvlNode<char>* pNodeTmp3 = NULL; CAvlNode<char>* pNodeTmp4 = NULL; CAvlNode<char>* pNodeTmp5 = NULL; // C-D pNodeTmp1 = tree.MakeNewNode('-'); tree.insertNode(pNodeTmp1, NODE_LEFT, 'C'); tree.insertNode(pNodeTmp1, NODE_RIGHT, 'D'); // E-F pNodeTmp2 = tree.MakeNewNode('-'); tree.insertNode(pNodeTmp2, NODE_LEFT, 'E'); tree.insertNode(pNodeTmp2, NODE_RIGHT, 'F'); // B*(C-D) pNodeTmp3 = tree.MakeNewNode('*'); tree.insertNode(pNodeTmp3, NODE_LEFT, 'B'); tree.insertNode(pNodeTmp3, NODE_RIGHT, pNodeTmp1); // B*(C-D)/(E-F) pNodeTmp4 = tree.MakeNewNode('/'); tree.insertNode(pNodeTmp4, NODE_LEFT, pNodeTmp3); tree.insertNode(pNodeTmp4, NODE_RIGHT, pNodeTmp2); // A + B*(C-D)/(E-F) pNodeTmp5 = tree.MakeNewNode('+'); tree.insertNode(pNodeTmp5, NODE_LEFT, 'A'); tree.insertNode(pNodeTmp5, NODE_RIGHT, pNodeTmp4); // A + B*(C-D)/(E-F) - G pRootNode = tree.insertRootNode('-'); tree.insertNode(pRootNode, NODE_LEFT, pNodeTmp5); tree.insertNode(pRootNode, NODE_RIGHT, 'G'); //---------------------------------------------------------------------- // 遍历树 - 前序打印 ok //---------------------------------------------------------------------- printf("tree.TraverseDLR:\n"); tree.TraverseDLR(tree.getRoot(), &fnPrintNode_AsCharValue); ///< 非递归实现 printf("\n"); //---------------------------------------------------------------------- // 遍历树 - 中序打印 //---------------------------------------------------------------------- // A + B * C - D / E - F - G printf("tree.TraverseLDR:\n"); tree.TraverseLDR(tree.getRoot(), &fnPrintNode_AsCharValue); ///< 非递归实现 printf("\n"); //---------------------------------------------------------------------- // 遍历树 - 逆序打印 ok //---------------------------------------------------------------------- // A B C D - * E F - / + G - printf("tree.TraverseLRD:\n"); tree.TraverseLRD(tree.getRoot(), &fnPrintNode_AsCharValue); ///< 非递归实现 printf("\n"); // A + B*(C-D)/(E-F) - G // 后序遍历表达式的模拟计算 // A B C D - * E F - / + G - // A B (C-D) * E F - / + G - // A B*(C-D) E F - / + G - // A B*(C-D) (E-F) / + G - // A B*(C-D)/(E-F) + G - // A+B*(C-D)/(E-F) G - // A+B*(C-D)/(E-F)-G } bool fnPrintNode_AsCharValue(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt) { if (NULL != pNodeOpt) printf("%c ", (char)pNodeOpt->m_Element); else printf(" "); return true; } bool fnPrintNode_Basic(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt) { if (NULL != pNodeOpt) printf("[L%d:%d] ", pNodeOpt->m_BF, pNodeOpt->m_Element); else printf(" "); return true; } bool fnPrintNode_Detail(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt) { if (NULL != pNodeOpt) { // [结点本身地址][层数:节点值] [父节点][左孩子][右孩子] printf("[%p][L%d:%d] [%p][%p][%p]\n", pNodeOpt, pNodeOpt->m_BF, pNodeOpt->m_Element, pNodeOpt->m_pParent, pNodeOpt->m_pChildLeft, pNodeOpt->m_pChildRight); } else printf(" "); return true; } void clear_cin() { cin.clear(); cin.sync(); }
模板实现
// LsTree.h: interface for the CAvl class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_LSTREE_H__4898D3E6_65B2_4A17_9CA5_910BEF38E313__INCLUDED_) #define AFX_LSTREE_H__4898D3E6_65B2_4A17_9CA5_910BEF38E313__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #define NODE_LEFT true #define NODE_RIGHT false #include <iostream> using namespace std; #include <stddef.h> #include <assert.h> #include "LsStack.h" #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif ///---------------------------------------------------------------------- /// 模板定义 ///---------------------------------------------------------------------- template<typename T> class CAvlNode { public: CAvlNode() : m_Element(0) , m_BF(1) , m_pParent(NULL) , m_pChildLeft(NULL) , m_pChildRight(NULL) {} CAvlNode(T Element) : m_Element(Element) , m_BF(1) , m_pParent(NULL) , m_pChildLeft(NULL) , m_pChildRight(NULL) {} ~CAvlNode() { #ifdef _DEBUG printf(">> ~CAvlNode() %p\n", this); #endif } T m_Element; ///< 元素值 int m_BF;// 树节点的平衡因子(Balance Factor) CAvlNode<T>* m_pParent; ///< 父节点 CAvlNode<T>* m_pChildLeft; ///< 左孩子结点 CAvlNode<T>* m_pChildRight; ///< 右孩子结点 }; template<typename T> class CAvl { public: CAvl() : m_pRoot(NULL), m_nNodeCounter(0) {} virtual ~CAvl() {free(m_pRoot);} void adjustBf(CAvlNode<T>* pNode); ///< 调整节点的平衡因子 void adjustBf(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 调整节点的平衡因子 void rotateL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 左旋 void rotateR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 右旋 void rotateLR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 左双旋(先左后右) void rotateRL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 右双旋(先右后左) int BF(CAvlNode<T>* pNode); ///< 取节点的平衡因子 CAvlNode<T>* insert(T Element); ///< 插入有序结点 CAvlNode<T>* find(T Element); ///< 在有序树中查找结点 /// 在pNode的左边找最右边的结点 CAvlNode<T>* findRightMaxOnNodeLeft(CAvlNode<T>* pNode); /// 在pNode的右边找最左边的结点 CAvlNode<T>* findLeftMinOnNodeRight(CAvlNode<T>* pNode); bool remove(T Element); ///< 在有序树中移除结点(by结点值) bool remove(CAvlNode<T>* pNodeToDel); ///< 在有序树中移除结点(by结点指针) private: bool removeChildNone(CAvlNode<T>* pNodeToDel); bool removeChildOne(CAvlNode<T>* pNodeToDel); bool removeChildTwo(CAvlNode<T>* pNodeToDel); bool removeChildTwoUseLeft(CAvlNode<T>* pNodeToDel); ///< 用左边最大的替换 bool removeChildTwoUseRight(CAvlNode<T>* pNodeToDel); ///< 用右边最小的替换 /// 用找到的节点指针替换并删除旧节点 bool removeChildTwoUseNew(CAvlNode<T>* pNodeToDel, CAvlNode<T>* pNodeNew); public: CAvlNode<T>* insertRootNode(T Element); CAvlNode<T>* MakeNewNode(T Element); CAvlNode<T>* insertNode(CAvlNode<T>* pNode, bool isLeft, T Element); CAvlNode<T>* insertNode(CAvlNode<T>* pNode, bool isLeft, CAvlNode<T>* pNodeChildExist); CAvlNode<T>* getRoot() {return m_pRoot;} /// 回调函数需要的声明, 必须在类模板内部定义 typedef bool (*PFN_CALLBACK_TRAVERSETREE_TREE)(CAvl<T>* pTree, const CAvlNode<T>*& pNodeOpt); /// 用非递归实现遍历, 由回调操作遍历到的节点 void TraverseDLR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb); ///< 前序 void TraverseLDR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb); ///< 中序 void TraverseLRD(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb); ///< 后序 void free(CAvlNode<T>* pTreeNode); ///< 释放资源 private: CAvlNode<T>* m_pRoot; size_t m_nNodeCounter; ///< 树结点计数器, 代表树节点总数 }; ///---------------------------------------------------------------------- /// 模板实现 ///---------------------------------------------------------------------- template<typename T> bool fnDelNode(CAvl<T>* pTree, const CAvlNode<T>*& pNodeOpt) { if ((NULL == pTree) || (NULL == pNodeOpt)) return false; return pTree->remove((CAvlNode<T>*)pNodeOpt); } template<typename T> void CAvl<T>::free(CAvlNode<T>* pTreeNode) { /// 按照LRD后序释放资源合理 TraverseLRD(pTreeNode, fnDelNode); } template<typename T> void CAvl<T>::TraverseDLR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb) { CLsStack<CAvlNode<T>*> stack; if (NULL != pTreeNode) stack.push(pTreeNode); while (!stack.isEmpty()) { pTreeNode = stack.pop(); if (NULL != pTreeNode) { if (NULL != pfnCb) pfnCb(this, pTreeNode); if (NULL != pTreeNode->m_pChildRight) stack.push(pTreeNode->m_pChildRight); if (NULL != pTreeNode->m_pChildLeft) stack.push(pTreeNode->m_pChildLeft); } } } template<typename T> void CAvl<T>::TraverseLDR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb) { CLsStack<CAvlNode<T>*> stack; while ((NULL != pTreeNode) || !stack.isEmpty()) { if (NULL != pTreeNode) { stack.push(pTreeNode); pTreeNode = pTreeNode->m_pChildLeft; } else { pTreeNode = stack.pop(); if (NULL != pfnCb) (*pfnCb)(this, pTreeNode); pTreeNode = pTreeNode->m_pChildRight; } } } template<typename T> void CAvl<T>::TraverseLRD(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb) { bool isNodeNoAnyChild = false; ///< 是树叶 bool isNodeNoRightChild = false; ///< 没有右孩子或右孩子已经遍历过 CLsStack<CAvlNode<T>*> stack; CAvlNode<T>* pLastNode = NULL; while (1) { /// 遍历并压栈当前结点到当前结点的最后一个左孩子 while (NULL != pTreeNode) { stack.push(pTreeNode); pTreeNode = pTreeNode->m_pChildLeft; } if (stack.isEmpty()) break; pTreeNode = stack.pop(); isNodeNoAnyChild = ((NULL == pTreeNode->m_pChildLeft) && (NULL == pTreeNode->m_pChildRight)); isNodeNoRightChild = ((NULL == pTreeNode->m_pChildRight) || (pTreeNode->m_pChildRight == pLastNode)); if (isNodeNoAnyChild || isNodeNoRightChild) { /// 符合LRD遍历操作当前结点的条件 /// 如果是叶子, 执行回调 /// 如果没有右孩子或右孩子已经遍历过, 执行回调 if (NULL != pfnCb) (*pfnCb)(this, pTreeNode); pLastNode = pTreeNode; ///< ! pTreeNode = NULL; ///< ! } else { /// 当前结点入栈, 当前结点变为右孩子 if (NULL != pTreeNode) { stack.push(pTreeNode); pTreeNode = pTreeNode->m_pChildRight; } } } } template<typename T> CAvlNode<T>* CAvl<T>::insertRootNode(T Element) { if (NULL == m_pRoot) { m_pRoot = new CAvlNode<T>(Element); } return m_pRoot; } template<typename T> bool CAvl<T>::remove(T Element) { CAvlNode<T>* pNodeToDel = find(Element); if (NULL == pNodeToDel) return false; return remove(pNodeToDel); } template<typename T> bool CAvl<T>::remove(CAvlNode<T>* pNodeToDel) { if (NULL == pNodeToDel) return false; else if ((NULL == pNodeToDel->m_pChildLeft) && (NULL == pNodeToDel->m_pChildRight)) return removeChildNone(pNodeToDel); else if ((NULL != pNodeToDel->m_pChildLeft) && (NULL != pNodeToDel->m_pChildRight)) return removeChildTwo(pNodeToDel); else return removeChildOne(pNodeToDel); } template<typename T> bool CAvl<T>::removeChildNone(CAvlNode<T>* pNodeToDel) { if (NULL == pNodeToDel) return false; /// 删除结点后, 只影响父节点 if (NULL == pNodeToDel->m_pParent) m_pRoot = NULL; ///< 要删除的是根结点 else if (pNodeToDel->m_pParent->m_pChildLeft == pNodeToDel) pNodeToDel->m_pParent->m_pChildLeft = NULL; else pNodeToDel->m_pParent->m_pChildRight = NULL; adjustBf(pNodeToDel); delete pNodeToDel; m_nNodeCounter--; return true; } template<typename T> bool CAvl<T>::removeChildOne(CAvlNode<T>* pNodeToDel) { CAvlNode<T>* pNodeChild = NULL; ///< pNodeToDel的独子结点 if (NULL == pNodeToDel) return false; /// 删除结点后, 影响父节点和子节点 if (NULL != pNodeToDel->m_pChildLeft) pNodeChild = pNodeToDel->m_pChildLeft; else pNodeChild = pNodeToDel->m_pChildRight; if (NULL == pNodeToDel->m_pParent) m_pRoot = pNodeChild; else { if (pNodeToDel->m_pParent->m_pChildLeft == pNodeToDel) pNodeToDel->m_pParent->m_pChildLeft = pNodeChild; else pNodeToDel->m_pParent->m_pChildRight = pNodeChild; } pNodeChild->m_pParent = pNodeToDel->m_pParent; adjustBf(pNodeToDel); delete pNodeToDel; m_nNodeCounter--; return true; } template<typename T> bool CAvl<T>::removeChildTwo(CAvlNode<T>* pNodeToDel) { /// 在有序2叉树中 /// 删除一个有2个孩子的结点后, 用孩子族谱中位置最接近本结点的后代继位 /// 如果从左边找, 继位者是左边最大的 /// 如果是从右边找, 继位者是右边最小的 /// 使用下列方法之一就可以 // return removeChildTwoUseLeft(pNodeToDel); return removeChildTwoUseRight(pNodeToDel); } template<typename T> bool CAvl<T>::removeChildTwoUseLeft(CAvlNode<T>* pNodeToDel) { CAvlNode<T>* pSubNodeAsParent = NULL; if (NULL == pNodeToDel) return false; /// 从被删除节点的左边找到最大的一个节点 pSubNodeAsParent = findRightMaxOnNodeLeft(pNodeToDel); assert(NULL != pSubNodeAsParent); return removeChildTwoUseNew(pNodeToDel, pSubNodeAsParent); } template<typename T> bool CAvl<T>::removeChildTwoUseRight(CAvlNode<T>* pNodeToDel) { CAvlNode<T>* pSubNodeAsParent = NULL; if (NULL == pNodeToDel) return false; /// 从被删除节点的右边找到最小的一个节点 pSubNodeAsParent = findLeftMinOnNodeRight(pNodeToDel); assert(NULL != pSubNodeAsParent); return removeChildTwoUseNew(pNodeToDel, pSubNodeAsParent); } template<typename T> bool CAvl<T>::removeChildTwoUseNew( CAvlNode<T>* pNodeToDel, CAvlNode<T>* pNodeNew) { if ((NULL == pNodeToDel) || (NULL == pNodeNew)) return false; /// 将新节点赋值到要删除的节点 pNodeToDel->m_Element = pNodeNew->m_Element; return remove(pNodeNew); } template<typename T> CAvlNode<T>* CAvl<T>::findRightMaxOnNodeLeft(CAvlNode<T>* pNode) { /// 在pNode的左边找最右边的结点 if ((NULL == pNode) || (NULL == pNode->m_pChildLeft)) return NULL; pNode = pNode->m_pChildLeft; while (NULL != pNode->m_pChildRight) pNode = pNode->m_pChildRight; return pNode; } template<typename T> CAvlNode<T>* CAvl<T>::findLeftMinOnNodeRight(CAvlNode<T>* pNode) { /// 在pNode的右边找最左边的结点 if ((NULL == pNode) || (NULL == pNode->m_pChildRight)) return NULL; pNode = pNode->m_pChildRight; while (NULL != pNode->m_pChildLeft) pNode = pNode->m_pChildLeft; return pNode; } template<typename T> CAvlNode<T>* CAvl<T>::find(T Element) { CAvlNode<T>* pNodeCur = getRoot(); while (NULL != pNodeCur) { if (Element > pNodeCur->m_Element) pNodeCur = pNodeCur->m_pChildRight; ///< 新节点在右边 else if (Element < pNodeCur->m_Element) pNodeCur = pNodeCur->m_pChildLeft; ///< 新节点在左边 else break; ///< 找到了相等的树结点值, 结点为pNodeCur } return pNodeCur; } template<typename T> CAvlNode<T>* CAvl<T>::insert(T Element) { bool bInsertOk = false; CAvlNode<T>* pNewNode = new CAvlNode<T>(Element); CAvlNode<T>* pNodeCur = NULL; if (NULL != pNewNode) m_nNodeCounter++; if (NULL == m_pRoot) { /// 在空树中插入根节点 m_pRoot = pNewNode; return pNewNode; } /// 在非空树中, 插入到一个空结点 pNodeCur = m_pRoot; while (NULL != pNodeCur) { if (Element > pNodeCur->m_Element) { /// 应该将新节点插入当前结点右边 if (NULL == pNodeCur->m_pChildRight) { pNodeCur->m_pChildRight = pNewNode; bInsertOk = true; break; } pNodeCur = pNodeCur->m_pChildRight; continue; } else if (Element < pNodeCur->m_Element) { /// 应该将新节点插入当前结点左边 if (NULL == pNodeCur->m_pChildLeft) { pNodeCur->m_pChildLeft = pNewNode; bInsertOk = true; break; } pNodeCur = pNodeCur->m_pChildLeft; continue; } break; ///< 找到了相等的树结点值, do nothing } if (bInsertOk) { pNewNode->m_pParent = pNodeCur; adjustBf(pNewNode); } return pNewNode; } template<typename T> CAvlNode<T>* CAvl<T>::MakeNewNode(T Element) { CAvlNode<T>* pNewNode = new CAvlNode<T>(Element); return pNewNode; } template<typename T> CAvlNode<T>* CAvl<T>::insertNode(CAvlNode<T>* pNode, bool isLeft, T Element) { CAvlNode<T>* pNodeChild = NULL; if (NULL != pNode) { pNodeChild = new CAvlNode<T>(); pNodeChild->m_Element = Element; pNodeChild->m_pParent = pNode; if (isLeft) pNode->m_pChildLeft = pNodeChild; else pNode->m_pChildRight = pNodeChild; } return pNode; } template<typename T> CAvlNode<T>* CAvl<T>::insertNode(CAvlNode<T>* pNode, bool isLeft, CAvlNode<T>* pNodeChildExist) { if (NULL != pNode) { if (NULL != pNodeChildExist) pNodeChildExist->m_pParent = pNode; if (isLeft) pNode->m_pChildLeft = pNodeChildExist; else pNode->m_pChildRight = pNodeChildExist; } return pNodeChildExist; } template<typename T> int CAvl<T>::BF(CAvlNode<T>* pNode) { return (NULL != pNode) ? pNode->m_BF : 0; } template<typename T> void CAvl<T>::adjustBf(CAvlNode<T>* pNode) { CAvlNode<T>* pParent = (NULL != pNode) ? pNode->m_pParent : NULL; /* G G AD1 AD2 A AD2 ==> AD1 AD3 B AD3 A B */ /// AD mean's "node need adjust" CAvlNode<T>* pAD1 = NULL; ///< 入参节点pNode的父节点 CAvlNode<T>* pAD2 = NULL; ///< pAD1 偏重的子树节点 CAvlNode<T>* pAD3 = NULL; ///< pAD2 偏重的子树节点 int iBfLeft = 0; ///< 左树的平衡因子 int iBfRight = 0; ///< 右树的平衡因子 while (NULL != pParent) { iBfLeft = BF(pParent->m_pChildLeft); iBfRight = BF(pParent->m_pChildRight); /// 调整父节点的平衡因子 pParent->m_BF = max(iBfLeft, iBfRight) + 1; /// 检查平衡 if (abs(iBfLeft - iBfRight) > 1) { /// 不平衡, 需要调整AVL为平衡 pAD1 = pParent; if (iBfLeft > iBfRight) pAD2 = pAD1->m_pChildLeft; else pAD2 = pAD1->m_pChildRight; if (NULL != pAD2) { if (BF(pAD2->m_pChildLeft) > BF(pAD2->m_pChildRight)) pAD3 = pAD2->m_pChildLeft; else pAD3 = pAD2->m_pChildRight; adjustBf(pAD1, pAD2, pAD3); } } /// 将父节点链都调整为AVL平衡 pParent = pParent->m_pParent; } } template<typename T> void CAvl<T>::adjustBf(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) { if ((pAD2 == pAD1->m_pChildRight) && (pAD3 == pAD2->m_pChildRight)) { /// 不平衡且有序, 右斜树, 经过一次左旋平衡 rotateL(pAD1, pAD2, pAD3); } else if ((pAD2 == pAD1->m_pChildLeft) && (pAD3 == pAD2->m_pChildLeft)) { /// 不平衡且有序, 左斜树, 经过一次右旋平衡 rotateR(pAD1, pAD2, pAD3); } else if ((pAD2 == pAD1->m_pChildLeft) && (pAD3 == pAD2->m_pChildRight)) { /// 不平衡且无序, 经过左双旋平衡 rotateLR(pAD1, pAD2, pAD3); } else if ((pAD2 == pAD1->m_pChildRight) && (pAD3 == pAD2->m_pChildLeft)) { /// 不平衡且无序, 经过右双旋平衡 rotateRL(pAD1, pAD2, pAD3); } } template<typename T> void CAvl<T>::rotateL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) { ///< 左旋 /* G G AD1 AD2 A AD2 ==> AD1 AD3 B AD3 A B */ CAvlNode<T>* pNodeA = pAD1->m_pChildLeft; CAvlNode<T>* pNodeB = pAD2->m_pChildLeft; CAvlNode<T>* pNodeC = pAD3; CAvlNode<T>* pNodeG = pAD1->m_pParent; /// 更新pNodeB if (NULL != pNodeB) pNodeB->m_pParent = pAD1; /// 更新pNodeG if (NULL != pNodeG) { if (pAD1 == pNodeG->m_pChildLeft) pNodeG->m_pChildLeft = pAD2; else pNodeG->m_pChildRight = pAD2; } else m_pRoot = pAD2; /// 更新pAD1 pAD1->m_pChildRight = pNodeB; pAD1->m_pParent = pAD2; /// 更新pAD2 pAD2->m_pChildLeft = pAD1; pAD2->m_pParent = pNodeG; //调整pAD1,pAD2的高度 pAD1->m_BF = max(BF(pAD1->m_pChildLeft), BF(pAD1->m_pChildRight)) + 1; pAD2->m_BF = max(BF(pAD2->m_pChildLeft), BF(pAD2->m_pChildRight)) + 1; } template<typename T> void CAvl<T>::rotateR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) { ///< 右旋 /* G G AD1 AD2 AD2 A ==> AD3 AD1 AD3 B B A */ CAvlNode<T>* pNodeA = pAD1->m_pChildRight; CAvlNode<T>* pNodeB = pAD2->m_pChildRight; CAvlNode<T>* pNodeC = pAD3; CAvlNode<T>* pNodeG = pAD1->m_pParent; /// 更新pNodeB if (NULL != pNodeB) pNodeB->m_pParent = pAD1; /// 更新pNodeG if (NULL != pNodeG) { if (pAD1 == pNodeG->m_pChildLeft) pNodeG->m_pChildLeft = pAD2; else pNodeG->m_pChildRight = pAD2; } else m_pRoot = pAD2; /// 更新pAD1 pAD1->m_pParent = pAD2; pAD1->m_pChildLeft = pNodeB; /// 更新pAD2 pAD2->m_pChildRight = pAD1; pAD2->m_pParent = pNodeG; //调整pAD1,pAD2的高度 pAD1->m_BF = max(BF(pAD1->m_pChildLeft), BF(pAD1->m_pChildRight)) + 1; pAD2->m_BF = max(BF(pAD2->m_pChildLeft), BF(pAD2->m_pChildRight)) + 1; } template<typename T> void CAvl<T>::rotateLR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) { ///< 左双旋(先左后右) rotateL(pAD2, pAD3, NULL); rotateR(pAD1, pAD3, pAD2); } template<typename T> void CAvl<T>::rotateRL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) { ///< 右双旋(先右后左) rotateR(pAD2, pAD3, NULL); rotateL(pAD1, pAD3, pAD2); } #endif // !defined(AFX_LSTREE_H__4898D3E6_65B2_4A17_9CA5_910BEF38E313__INCLUDED_)
// LsStack.h: interface for the CLsLinkedList class. // ////////////////////////////////////////////////////////////////////// #if !defined(LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632) #define LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632 #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "LsDoublyLinkedList.h" /** 栈 栈也是线性表. 栈是先进后出, 只操作栈顶的数据结构. 栈是可以回溯的 栈可以用来计算用来制作堆栈机, 用堆栈机算法来模拟逆波兰表达式的运算结果, 可以模拟汇编指令的执行, 用于虚拟机. 实现方法 * 用链表类实现 继承于链表, 只在头部操作(增加,删除). * 用数组类实现 继承于数组, 只在尾部操作(增加,删除). */ template<typename T> class CLsStack : public CLsLinkedList<T> { public: CLsStack() {} virtual ~CLsStack() {} void push(T Element); T pop(); }; template<typename T> void CLsStack<T>::push(T Element) { addHead(Element); } template<typename T> T CLsStack<T>::pop() { T Rc = (T)0; if (getLength() > 0) { Rc = *getHead(); removeHead(); } return Rc; } #endif // !defined(LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
// LsDoublyLinkedList.h: interface for the CLsLinkedList class. // ////////////////////////////////////////////////////////////////////// #if !defined(LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632) #define LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632 /** 链表总结 空间 链式存储 时间复杂度 尽量避免提供非常量阶的接口 增加操作: O(1) 常量阶, 快 删除操作: O(1) 常量阶, 快 修改操作:O(1) 快(条件:知道位置, 用的是先前返回的位置类或结点指针) 查询操作:O(n) 线性阶, 慢 随机访问:O(n) 线性阶, 慢 使用场合 * 问题规模不确定 * 随机访问频率低 * 数据更新频率高(主要指的是添加和删除操作) 缺点 * 查询速度慢(数组和链表查询速度都慢) 原生new的时间复杂度 new实现是线性阶. 调用的memset是线性阶, 有循环操作. HeapAlloc中没源码, 但是有循环操作, 是线性阶. new不影响时间增长率. 结论 当算法中, new次数较少时, 可以忽略new对算法时间复杂度的影响. 当new次数较多时, 可以一次多new几个元素(e.g. 10个), 下次就不用new, 直接取已经new好的数据操作, 等用完了, 才再次new几个元素出来. 这样对new操作做优化, 等于自己做堆管理, 需要再做一个链表, 将new出来的10个一组的小块内存空间管理起来, 当一个类指针不用了, 就称为闲置空间, 放在内存池中. 下次不用再申请了, 可以复用. 等链表析构时, 链表的原生操作完成后, 再一块释放内存池. */ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 /// ---------------------------------------------------------------------- /// CLsLinkedList 双链表 定义 /// ---------------------------------------------------------------------- template <typename T> class CLsLinkedList { public: /// ---------------------------------------------------------------------- /// CLsLinkedNode 定义 /// ---------------------------------------------------------------------- /// LsDoublyLinkedList's Node template <typename T> struct CLsLinkedNode { friend CLsLinkedList<T>; ///< 不需要前向声明, 用到的时候才检查 friend CLsLinkedList<T>::iterator; private: CLsLinkedNode(T Elem) :m_Elem(Elem) ,m_pNext(NULL) ,m_pPrev(NULL) {} ~CLsLinkedNode() {} T m_Elem; //数据元素 CLsLinkedNode<T>* m_pPrev; //前驱 CLsLinkedNode<T>* m_pNext; //后继 }; /// ---------------------------------------------------------------------- /// 正向迭代器 定义 /// ---------------------------------------------------------------------- class iterator { friend class CLsLinkedList<T>; public: iterator() { m_pNode = NULL; } iterator(CLsLinkedNode<T>* pNode) { m_pNode = pNode; } iterator operator++() { m_pNode = m_pNode->m_pNext; return m_pNode; } iterator operator++(int) { CLsLinkedNode<T> *pTemp = m_pNode; m_pNode = m_pNode->m_pNext; return pTemp; } iterator operator--() { m_pNode = m_pNode->m_pPrev; return m_pNode; } iterator operator--(int) { CLsLinkedNode<T> *pTemp = m_pNode; m_pNode = m_pNode->m_pPrev; return pTemp; } T& operator* () { return m_pNode->m_Elem; } bool operator!= (const iterator& obj) { return m_pNode != obj.m_pNode; } bool operator== (const iterator& obj) { return m_pNode == obj.m_pNode; } private: CLsLinkedNode<T>* GetNode() { return m_pNode; } private: CLsLinkedNode<T>* m_pNode; }; public: iterator begin() { return m_pHead; } iterator end() { return NULL; } public: CLsLinkedList(); virtual ~CLsLinkedList(); /// 只提供O(1)的接口^_^ iterator getTail() const; iterator getHead() const; inline bool isEmpty() const; inline size_t getLength() const; //表长 void clear(); iterator addTail(T newElem); bool removeTail(); iterator addHead(T newElem); bool removeHead(); T getAt(iterator it) const; void setAt(iterator it, T newElem); bool removeAt(iterator it); bool insert(iterator it, T newElem); private: CLsLinkedNode<T>* m_pHead; //头结点 CLsLinkedNode<T>* m_pTail; //尾结点 size_t m_nLength; }; /// ---------------------------------------------------------------------- /// CLsLinkedList 实现 /// ---------------------------------------------------------------------- template <typename T> inline size_t CLsLinkedList<T>::getLength() const { return m_nLength; } template <typename T> inline bool CLsLinkedList<T>::isEmpty() const { return (NULL == m_pHead) ? true : false; } template <typename T> CLsLinkedList<T>::CLsLinkedList() :m_pHead(NULL) ,m_pTail(NULL) ,m_nLength(0) {} template <typename T> CLsLinkedList<T>::~CLsLinkedList() { clear(); } template <typename T> void CLsLinkedList<T>::clear() { while (!isEmpty()) { removeTail(); } } template <typename T> T CLsLinkedList<T>::getAt(CLsLinkedList::iterator it) const { return *it; } template <typename T> void CLsLinkedList<T>::setAt(CLsLinkedList::iterator it, T newElem) { *it = newElem; } template <typename T> bool CLsLinkedList<T>::insert(CLsLinkedList::iterator it, T newElem) { CLsLinkedNode<T>* pNewNode = NULL; CLsLinkedNode<T>* pPrev = NULL; CLsLinkedNode<T>* pNext = NULL; pPrev = it.GetNode(); if (NULL == pPrev) { return false; } pNewNode = new CLsLinkedNode<T>(newElem); pNext = pPrev->m_pNext; /* 1 2 3 [6] 4 5 3.next = 6 4.prev = 6 6.prev = 3 6.next = 4 1 2 3 4 5 [6] */ pPrev->m_pNext = pNewNode; if (NULL != pNext) { pNext->m_pPrev = pNewNode; } pNewNode->m_pPrev = pPrev; pNewNode->m_pNext = pNext; m_nLength++; return true; } template <typename T> bool CLsLinkedList<T>::removeTail() { bool bRc = false; CLsLinkedNode<T>* pPrev = NULL; if (NULL == m_pHead) { return false; } //1 2 [3] if (NULL != m_pTail) { pPrev = m_pTail->m_pPrev; if (NULL != pPrev) pPrev->m_pNext = NULL; else m_pHead = NULL; delete m_pTail; bRc = true; m_pTail = pPrev; m_nLength--; } return bRc; } template <typename T> bool CLsLinkedList<T>::removeHead() { if (NULL == m_pHead) return false; //[1] 2 3 CLsLinkedNode<T>* pNext = m_pHead->m_pNext; if (NULL != pNext) pNext->m_pPrev = NULL; else m_pTail = NULL; delete m_pHead; m_nLength--; m_pHead = pNext; return true; } template <typename T> bool CLsLinkedList<T>::removeAt(CLsLinkedList::iterator it) { CLsLinkedNode<T>* pDelNode = it.GetNode(); CLsLinkedNode<T>* pPrev = NULL; CLsLinkedNode<T>* pNext = NULL; if ((NULL == m_pHead) || (NULL == pDelNode)) return false; /* 1 2 [3] 4 5 2.next = 4 4.prev = 2 [1] 2 3 4 5 1 2 3 4 [5] [1] */ pPrev = pDelNode->m_pPrev; pNext = pDelNode->m_pNext; if (NULL != pPrev) pPrev->m_pNext = pNext; else m_pHead = pNext; if (NULL != pNext) pNext->m_pPrev = pPrev; else m_pTail = pPrev; delete pDelNode; m_nLength--; return true; } template <typename T> CLsLinkedList<T>::iterator CLsLinkedList<T>::addTail(T newElem) { CLsLinkedList<T>::CLsLinkedNode<T>* pNewNode = new CLsLinkedList<T>::CLsLinkedNode<T>(newElem); //空表 if (NULL == m_pHead) m_pHead = m_pTail = pNewNode; else { //1 2 3 4 5 [6] //5.next = 6 6.prev = 5 tail = 6 m_pTail->m_pNext = pNewNode; pNewNode->m_pPrev = m_pTail; m_pTail = pNewNode; } m_nLength++; return pNewNode; } template <typename T> CLsLinkedList<T>::iterator CLsLinkedList<T>::addHead(T newElem) { CLsLinkedList<T>::CLsLinkedNode<T> *pNewNode = new CLsLinkedList<T>::CLsLinkedNode<T>(newElem); //空表 if (NULL == m_pHead) m_pHead = m_pTail = pNewNode; else { //[6] 1 2 3 4 5 //1.prev = 6 6.next = 1 head = 6 m_pHead->m_pPrev = pNewNode; pNewNode->m_pNext = m_pHead; m_pHead = pNewNode; } m_nLength++; return pNewNode; } template <typename T> CLsLinkedList<T>::iterator CLsLinkedList<T>::getTail() const { return m_pTail; } template <typename T> CLsLinkedList<T>::iterator CLsLinkedList<T>::getHead() const { return m_pHead; } #endif // !defined(LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
相关文章推荐
- 读取音频文件的谱线
- 解决修改计算机名后tfs连接不上的错误
- 修改表触发器对应的序列号 (当增加或修改数据时需要用)
- 《从零开始学Swift》学习笔记(Day 59)——代码排版
- Fragment-学习笔记(一)
- 室内定位技术研发简介
- MySQL不支持中文、将编码修改为utf-8,仍不支持中文问题解决方案
- php表示 当天0点 和 24点的 时间戳
- 在使用Notepad++ WinSCP SFTP遇到的连接失败问题分析
- C#冒泡排序
- dbca静默建库
- ECS Linux下解压rar格式的压缩文件
- python基础入门学习笔记(Python环境搭建)
- spring自定义标签及获取注释里面的值
- VSTO:无法安装此应用程序,因为已安装具有相同标识的应用程序
- UITableView的分割线去除左侧15像素从最左边开始绘制
- table中thead保持不动,tbody滚动(2)
- installshield中杀死某一个进程
- PHP自动加载类
- 走进nginx事件驱动模型