📄 ptrlist.cpp
字号:
//---------------------------------------------------------------------------
// 名称:PtrList.cpp
// 功能:CPtrList类的源文件
// 版本:1.0
// 工具: Visual C++ 6.0
// 引入:无
// 引出:无
// 作者:刘健颖
// 时间:2004-05-26
//---------------------------------------------------------------------------
#include "stdafx.h"
#include "PtrList.h"
CPlex* PASCAL CPlex::Create(CPlex*& pHead, UINT_PTR nMax, UINT_PTR cbElement)
{
ATLASSERT(nMax > 0 && cbElement > 0);
CPlex* p = (CPlex*) new BYTE[sizeof(CPlex) + nMax * cbElement];
// may throw exception
p->pNext = pHead;
pHead = p; // change head (adds in reverse order for simplicity)
return p;
}
void CPlex::FreeDataChain() // free this one and links
{
CPlex* p = this;
while (p != NULL)
{
BYTE* bytes = (BYTE*) p;
CPlex* pNext = p->pNext;
delete[] bytes;
p = pNext;
}
}
CPtrList::CPtrList(int nBlockSize)
{
ATLASSERT(nBlockSize > 0);
m_nCount = 0;
m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
m_pBlocks = NULL;
m_nBlockSize = nBlockSize;
}
void CPtrList::RemoveAll()
{
ATLASSERT(this != NULL);
ATLASSERT(AtlIsValidAddress(this, sizeof(CPtrList)));
// destroy elements
m_nCount = 0;
m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
m_pBlocks->FreeDataChain();
m_pBlocks = NULL;
}
CPtrList::~CPtrList()
{
RemoveAll();
ATLASSERT(m_nCount == 0);
}
/////////////////////////////////////////////////////////////////////////////
// Node helpers
/*
* Implementation note: CNode's are stored in CPlex blocks and
* chained together. Free blocks are maintained in a singly linked list
* using the 'pNext' member of CNode with 'm_pNodeFree' as the head.
* Used blocks are maintained in a doubly linked list using both 'pNext'
* and 'pPrev' as links and 'm_pNodeHead' and 'm_pNodeTail'
* as the head/tail.
*
* We never free a CPlex block unless the List is destroyed or RemoveAll()
* is used - so the total number of CPlex blocks may grow large depending
* on the maximum past size of the list.
*/
CPtrList::CNode*
CPtrList::NewNode(CPtrList::CNode* pPrev, CPtrList::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;
}
}
ATLASSERT(m_pNodeFree != NULL); // we must have something
CPtrList::CNode* pNode = m_pNodeFree;
m_pNodeFree = m_pNodeFree->pNext;
pNode->pPrev = pPrev;
pNode->pNext = pNext;
m_nCount++;
ATLASSERT(m_nCount > 0); // make sure we don't overflow
pNode->data = 0; // start with zero
return pNode;
}
void CPtrList::FreeNode(CPtrList::CNode* pNode)
{
pNode->pNext = m_pNodeFree;
m_pNodeFree = pNode;
m_nCount--;
ATLASSERT(m_nCount >= 0); // make sure we don't underflow
// if no more elements, cleanup completely
if (m_nCount == 0)
RemoveAll();
}
/////////////////////////////////////////////////////////////////////////////
POSITION CPtrList::AddHead(void* 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;
m_nCount++;
return (POSITION) pNewNode;
}
POSITION CPtrList::AddTail(void* newElement)
{
CNode* pNewNode = NewNode(m_pNodeTail, NULL);
pNewNode->data = newElement;
if (m_pNodeTail != NULL)
m_pNodeTail->pNext = pNewNode;
else
m_pNodeHead = pNewNode;
m_pNodeTail = pNewNode;
m_nCount++;
return (POSITION) pNewNode;
}
void CPtrList::AddHead(CPtrList* pNewList)
{
ATLASSERT(pNewList != NULL);
ATLASSERT(AtlIsValidAddress(pNewList, sizeof(CPtrList)));
// add a list of same elements to head (maintain order)
POSITION pos = pNewList->GetTailPosition();
while (pos != NULL)
AddHead(pNewList->GetPrev(pos));
}
void CPtrList::AddTail(CPtrList* pNewList)
{
ATLASSERT(pNewList != NULL);
ATLASSERT(AtlIsValidAddress(pNewList, sizeof(CPtrList)));
// add a list of same elements
POSITION pos = pNewList->GetHeadPosition();
while (pos != NULL)
AddTail(pNewList->GetNext(pos));
}
void* CPtrList::RemoveHead()
{
ATLASSERT(m_pNodeHead != NULL); // don't call on empty list !!!
ATLASSERT(AtlIsValidAddress(m_pNodeHead, sizeof(CNode)));
CNode* pOldNode = m_pNodeHead;
void* returnValue = pOldNode->data;
m_pNodeHead = pOldNode->pNext;
if (m_pNodeHead != NULL)
m_pNodeHead->pPrev = NULL;
else
m_pNodeTail = NULL;
FreeNode(pOldNode);
m_nCount--;
return returnValue;
}
void* CPtrList::RemoveTail()
{
ATLASSERT(m_pNodeTail != NULL); // don't call on empty list !!!
ATLASSERT(AtlIsValidAddress(m_pNodeTail, sizeof(CNode)));
CNode* pOldNode = m_pNodeTail;
void* returnValue = pOldNode->data;
m_pNodeTail = pOldNode->pPrev;
if (m_pNodeTail != NULL)
m_pNodeTail->pNext = NULL;
else
m_pNodeHead = NULL;
FreeNode(pOldNode);
m_nCount--;
return returnValue;
}
POSITION CPtrList::InsertBefore(POSITION position, void* 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)
{
ATLASSERT(AtlIsValidAddress(pOldNode->pPrev, sizeof(CNode)));
pOldNode->pPrev->pNext = pNewNode;
}
else
{
ATLASSERT(pOldNode == m_pNodeHead);
m_pNodeHead = pNewNode;
}
pOldNode->pPrev = pNewNode;
m_nCount++;
return (POSITION) pNewNode;
}
POSITION CPtrList::InsertAfter(POSITION position, void* newElement)
{
if (position == NULL)
return AddTail(newElement); // insert after nothing -> tail of the list
// Insert it before position
CNode* pOldNode = (CNode*) position;
ATLASSERT(AtlIsValidAddress(pOldNode, sizeof(CNode)));
CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);
pNewNode->data = newElement;
if (pOldNode->pNext != NULL)
{
ATLASSERT(AtlIsValidAddress(pOldNode->pNext, sizeof(CNode)));
pOldNode->pNext->pPrev = pNewNode;
}
else
{
ATLASSERT(pOldNode == m_pNodeTail);
m_pNodeTail = pNewNode;
}
pOldNode->pNext = pNewNode;
m_nCount++;
return (POSITION) pNewNode;
}
void CPtrList::RemoveAt(POSITION position)
{
CNode* pOldNode = (CNode*) position;
ATLASSERT(AtlIsValidAddress(pOldNode, sizeof(CNode)));
// remove pOldNode from list
if (pOldNode == m_pNodeHead)
{
m_pNodeHead = pOldNode->pNext;
}
else
{
ATLASSERT(AtlIsValidAddress(pOldNode->pPrev, sizeof(CNode)));
pOldNode->pPrev->pNext = pOldNode->pNext;
}
if (pOldNode == m_pNodeTail)
{
m_pNodeTail = pOldNode->pPrev;
}
else
{
ATLASSERT(AtlIsValidAddress(pOldNode->pNext, sizeof(CNode)));
pOldNode->pNext->pPrev = pOldNode->pPrev;
}
m_nCount--;
FreeNode(pOldNode);
}
/////////////////////////////////////////////////////////////////////////////
// slow operations
POSITION CPtrList::FindIndex(int nIndex) const
{
if (nIndex >= m_nCount || nIndex < 0)
return NULL; // went too far
CNode* pNode = m_pNodeHead;
while (nIndex--)
{
ATLASSERT(AtlIsValidAddress(pNode, sizeof(CNode)));
pNode = pNode->pNext;
}
return (POSITION) pNode;
}
POSITION CPtrList::Find(void* searchValue, POSITION startAfter) const
{
CNode* pNode = (CNode*) startAfter;
if (pNode == NULL)
{
pNode = m_pNodeHead; // start at head
}
else
{
ATLASSERT(AtlIsValidAddress(pNode, sizeof(CNode)));
pNode = pNode->pNext; // start after the one specified
}
for (; pNode != NULL; pNode = pNode->pNext)
if (pNode->data == searchValue)
return (POSITION) pNode;
return NULL;
}
POSITION CPtrList::GetHeadPosition( ) const
{
return ( POSITION )m_pNodeHead;
}
POSITION CPtrList::GetTailPosition( ) const
{
return ( POSITION )m_pNodeTail;
}
void* CPtrList::GetNext(POSITION& rPosition)
{
CNode* pNode = (CNode*) rPosition;
ATLASSERT(AtlIsValidAddress(pNode, sizeof(CNode)));
rPosition = (POSITION) pNode->pNext;
return pNode->data;
}
void* CPtrList::GetNext(POSITION& rPosition) const
{
CNode* pNode = (CNode*) rPosition;
ATLASSERT(AtlIsValidAddress(pNode, sizeof(CNode)));
rPosition = (POSITION) pNode->pNext;
return pNode->data;
}
void*& CPtrList::GetPrev(POSITION& rPosition)
{
CNode* pNode = (CNode*) rPosition;
ATLASSERT(AtlIsValidAddress(pNode, sizeof(CNode)));
rPosition = (POSITION) pNode->pPrev;
return pNode->data;
}
void* CPtrList::GetPrev(POSITION& rPosition) const
{
CNode* pNode = (CNode*) rPosition;
ATLASSERT(AtlIsValidAddress(pNode, sizeof(CNode)));
rPosition = (POSITION) pNode->pPrev;
return pNode->data;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -