可以插入重复数据的AVL树模板实现
来源:互联网 发布:windows环境开发ios 编辑:程序博客网 时间:2024/04/27 15:43
@todo
插入重复Key之后的处理还没做, 应该返回一个迭代器.
测试代码
/// @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 nodevoid 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.insert(11); tree1.insert(11); tree1.insert(11); tree1.insert(11); 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) , m_pNextSameKeyIndex(NULL) , m_bDeleteNextSameKeyIndex(false) {} CAvlNode(T Element) : m_Element(Element) , m_BF(1) , m_pParent(NULL) , m_pChildLeft(NULL) , m_pChildRight(NULL) , m_pNextSameKeyIndex(NULL) , m_bDeleteNextSameKeyIndex(false) {} ~CAvlNode() { CAvlNode<T>* pNodeCur = m_pNextSameKeyIndex; CAvlNode<T>* pNodeNext = NULL;#ifdef _DEBUG printf(">> ~CAvlNode() %p\n", this);#endif if (m_bDeleteNextSameKeyIndex) { while (NULL != pNodeCur) { pNodeNext = pNodeCur->m_pNextSameKeyIndex; pNodeCur->m_bDeleteNextSameKeyIndex = false; delete pNodeCur; pNodeCur = pNodeNext; } } } /// 设置此标记, 防止递归删除CAvlNode层数太多的问题. bool m_bDeleteNextSameKeyIndex; ///< 是否删除同样值的链表 T m_Element; ///< 元素值 int m_BF;// 树节点的平衡因子(Balance Factor) CAvlNode<T>* m_pParent; ///< 父节点 CAvlNode<T>* m_pChildLeft; ///< 左孩子结点 CAvlNode<T>* m_pChildRight; ///< 右孩子结点 CAvlNode<T>* m_pNextSameKeyIndex; ///< 同样的关键字索引, 挂一个链表};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; pNodeToDel->m_bDeleteNextSameKeyIndex = true; 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) { CAvlNode<T>* pNodeTmp = NULL; if ((NULL == pNodeToDel) || (NULL == pNodeNew)) return false; /// 将新节点赋值到要删除的节点 pNodeToDel->m_Element = pNodeNew->m_Element; /// 交换链表 pNodeTmp = pNodeNew->m_pNextSameKeyIndex; pNodeNew->m_pNextSameKeyIndex = pNodeToDel->m_pNextSameKeyIndex; pNodeToDel->m_pNextSameKeyIndex = pNodeTmp; 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; } else { /// 找到了相等的树结点值 pNewNode->m_pNextSameKeyIndex = pNodeCur->m_pNextSameKeyIndex; pNodeCur->m_pNextSameKeyIndex = pNewNode; } break; } 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>(); pNewNode->m_Element = 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>(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)
0 0
- 可以插入重复数据的AVL树模板实现
- AVL树的模板实现
- AVL树的模板实现
- AVL树插入的简单实现
- C++模板实现的AVL树
- AVL树的C++模板类实现
- AVL树实现(插入删除)
- AVL树的插入_删除操作实现~
- AVL树插入、删除的分析与实现
- 二叉平衡树AVL插入删除操作的实现
- AVL树的插入与删除---Java实现
- AVL平衡树及插入操作的C语言实现
- AVL树的插入与删除(均为递归实现)
- AVL树的插入、删除及遍历C语言实现
- 算法-AVL树的插入
- AVL树的插入操作
- AVL树的插入算法
- C++模板实现二叉树(七 AVL树的删除)
- LeetCode8. String to Integer (atoi)
- lemon语法分析生成器
- CKEditor 4的初始化配置与开启上传功能(JAVA EE)
- java对称密码算法的使用DES/3DES/AES算法
- 12. Integer to Roman
- 可以插入重复数据的AVL树模板实现
- python环境搭建
- jQuery WeUI v0.1.0 发布了 - 微信公众账号开发者的福音
- cocos2dx的内存管理机制
- 在论坛中出现的比较难的sql问题:32(row_number函数+子查询 sql循环取差值)
- 欢迎使用CSDN-markdown编辑器
- cocos2dx的渲染机制
- nodejs关于session和cookie的问题
- 快速掌握Lua 5.3 —— 各种运算符以及各种声明