CList声明
template<class TYPE, class ARG_TYPE = const TYPE&> class CList : public CObject { protected: struct CNode { CNode* pNext; // 后指针 CNode* pPrev; // 前指针 TYPE data; // 数据 }; public: // Construction /* explicit */ CList(INT_PTR nBlockSize = 10); // Attributes (head and tail) // count of elements INT_PTR GetCount() const; // return m_nCount; INT_PTR GetSize() const; // return m_nCount; BOOL IsEmpty() const; // return m_nCount == 0; // peek at head or tail TYPE& GetHead(); // return m_pNodeHead->data; const TYPE& GetHead() const; TYPE& GetTail(); // return m_pNodeTail->data; const TYPE& GetTail() const; // Operations // get head or tail (and remove it) - don't call on empty list ! TYPE RemoveHead(); // 删除头部元素,并返回其元素值 TYPE RemoveTail(); // 删除尾部元素,并返回其元素值 // add before head or after tail POSITION AddHead(ARG_TYPE newElement); POSITION AddTail(ARG_TYPE newElement); // add another list of elements before head or after tail void AddHead(CList* pNewList); void AddTail(CList* pNewList); // remove all elements void RemoveAll(); // iteration POSITION GetHeadPosition() const; // return (POSITION) m_pNodeHead; POSITION GetTailPosition() const; // return (POSITION) m_pNodeTail; TYPE& GetNext(POSITION& rPosition); // return *Position++ const TYPE& GetNext(POSITION& rPosition) const; // return *Position++ TYPE& GetPrev(POSITION& rPosition); // return *Position-- const TYPE& GetPrev(POSITION& rPosition) const; // return *Position-- // getting/modifying an element at a given position TYPE& GetAt(POSITION position); const TYPE& GetAt(POSITION position) const; void SetAt(POSITION pos, ARG_TYPE newElement); void RemoveAt(POSITION position); // inserting before or after a given position POSITION InsertBefore(POSITION position, ARG_TYPE newElement); POSITION InsertAfter(POSITION position, ARG_TYPE newElement); // helper functions (note: O(n) speed) POSITION Find(ARG_TYPE searchValue, POSITION startAfter = NULL) const; // defaults to starting at the HEAD, return NULL if not found POSITION FindIndex(INT_PTR nIndex) const; // get the 'nIndex'th element (may return NULL) // Implementation protected: CNode* m_pNodeHead; // 指向链表头的指针 CNode* m_pNodeTail; // 指向链表尾的指针 INT_PTR m_nCount; // 元素个数 CNode* m_pNodeFree; // 空闲节点链表 struct CPlex* m_pBlocks; // 数据块载体链表 INT_PTR m_nBlockSize; // 每个数据块元素个数 CNode* NewNode(CNode*, CNode*); // 创建新节点 void FreeNode(CNode*); // 释放节点数据 public: ~CList(); void Serialize(CArchive&); #ifdef _DEBUG void Dump(CDumpContext&) const; void AssertValid() const; #endif };
RemoveHead 和 FreeNode 函数
// 删除头部元素,并返回其元素值 template<class TYPE, class ARG_TYPE> TYPE CList<TYPE, ARG_TYPE>::RemoveHead() { CNode* pOldNode = m_pNodeHead; TYPE returnValue = pOldNode->data; m_pNodeHead = pOldNode->pNext; if (m_pNodeHead != NULL) m_pNodeHead->pPrev = NULL; else m_pNodeTail = NULL; FreeNode(pOldNode); return returnValue; } // 释放节点 template<class TYPE, class ARG_TYPE> void CList<TYPE, ARG_TYPE>::FreeNode(CNode* pNode) { pNode->data.~TYPE(); pNode->pNext = m_pNodeFree; // 将节点加入空闲节点链表 m_pNodeFree = pNode; m_nCount--; // if no more elements, cleanup completely if (m_nCount == 0) RemoveAll(); }
AddHead(插入元素) 和 NewNode 函数
// 在链表头部插入值为newElement的元素 template<class TYPE, class ARG_TYPE> POSITION CList<TYPE, ARG_TYPE>::AddHead(ARG_TYPE newElement) { CNode* pNewNode = NewNode(NULL, m_pNodeHead); pNewNode->data = newElement; if (m_pNodeHead != NULL) m_pNodeHead->pPrev = pNewNode; else m_pNodeTail = pNewNode; m_pNodeHead = pNewNode; return (POSITION) pNewNode; } // 创建一个新节点 template<class TYPE, class ARG_TYPE> typename CList<TYPE, ARG_TYPE>::CNode* CList<TYPE, ARG_TYPE>::NewNode(CNode* pPrev, CNode* pNext) { if (m_pNodeFree == NULL) { // add another block CPlex* pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CNode)); // chain them into free list CNode* pNode = (CNode*) pNewBlock->data(); // free in reverse order to make it easier to debug pNode += m_nBlockSize - 1; for (INT_PTR i = m_nBlockSize-1; i >= 0; i--, pNode--) { pNode->pNext = m_pNodeFree; m_pNodeFree = pNode; } } CList::CNode* pNode = m_pNodeFree; m_pNodeFree = m_pNodeFree->pNext; pNode->pPrev = pPrev; pNode->pNext = pNext; m_nCount++; ::new( (void*)( &pNode->data ) ) TYPE; return pNode; }
AddHead函数(插入链表)
// 在链表头部插入pNewList所指链表 template<class TYPE, class ARG_TYPE> void CList<TYPE, ARG_TYPE>::AddHead(CList* pNewList) { // add a list of same elements to head (maintain order) POSITION pos = pNewList->GetTailPosition(); while (pos != NULL) AddHead(pNewList->GetPrev(pos)); }
RemoveAll函数
// 移除所有的元素 template<class TYPE, class ARG_TYPE> void CList<TYPE, ARG_TYPE>::RemoveAll() { // destroy elements CNode* pNode; for (pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext) pNode->data.~TYPE(); m_nCount = 0; m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL; m_pBlocks->FreeDataChain(); // 释放数据链 m_pBlocks = NULL; }
RemoveAt函数
// 移除指定位置的元素 template<class TYPE, class ARG_TYPE> void CList<TYPE, ARG_TYPE>::RemoveAt(POSITION position) { CNode* pOldNode = (CNode*) position; // remove pOldNode from list if (pOldNode == m_pNodeHead) m_pNodeHead = pOldNode->pNext; else pOldNode->pPrev->pNext = pOldNode->pNext; if (pOldNode == m_pNodeTail) m_pNodeTail = pOldNode->pPrev; else pOldNode->pNext->pPrev = pOldNode->pPrev; FreeNode(pOldNode); // 释放节点数据。 }
InsertBefore函数
// 在指定位置之前插入值为newElement的元素。 template<class TYPE, class ARG_TYPE> POSITION CList<TYPE, ARG_TYPE>::InsertBefore(POSITION position, ARG_TYPE newElement) { if (position == NULL) return AddHead(newElement); // insert before nothing -> head of the list // Insert it before position CNode* pOldNode = (CNode*) position; CNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode); pNewNode->data = newElement; if (pOldNode->pPrev != NULL) pOldNode->pPrev->pNext = pNewNode; else m_pNodeHead = pNewNode; pOldNode->pPrev = pNewNode; return (POSITION) pNewNode; }
Find函数
// 从startAfter后开始查找值为searchVaule元素,返回位置 template<class TYPE, class ARG_TYPE> POSITION CList<TYPE, ARG_TYPE>::Find(ARG_TYPE searchValue, POSITION startAfter) const { CNode* pNode = (CNode*) startAfter; if (pNode == NULL) pNode = m_pNodeHead; // start at head else pNode = pNode->pNext; // start after the one specified for (; pNode != NULL; pNode = pNode->pNext) if (CompareElements<TYPE>(&pNode->data, &searchValue)) return (POSITION)pNode; return NULL; }