[代码分享]自己写的双向链表模板

huanglin03 2015-06-17 11:56:46
不废话,直接上代码,
1、优点,采用堆分配,而不用NEW------话说堆是管理大量小数据的最佳方式,效率杠杠滴!
2、空间回收速度超级快,不用遂个释放,一次性全部回收
3、不需要借用任何其它类型就可以直接操作,没有像STL中的迭代器啊,还有MFC中的POSITION的多余概念,操作很方便。

求拍砖,求教育,求终身难忘,



//-----------------------------------------------------------------------------

#pragma once

typedef void* PNODE;

template<class TYPE>
class CXList
{
protected:
struct TNode{TNode* pNext;TNode* pPrev;TYPE data;};
ULONG m_nCount;
HANDLE m_hHeapMem;
TNode* m_pNodeHead;
TNode* m_pNodeTail;
TNode* m_pNodeFree;

protected:
void _FreeNode(TNode* pNode);
PNODE _NewNode(TNode* pPrev, TNode* pNext);

public:
CXList();
~CXList();
BOOL Initialize(ULONG nInitSize = 10);
void Uninitialize();

ULONG GetCount();
TYPE* GetHead();
TYPE* GetTail();
TYPE* GetAt(PNODE pNode);
TYPE* GetNext(PNODE pNode);
TYPE* GetPrev(PNODE pNode);
TYPE* operator[](UINT nIndex);

BOOL IsEmpty();
void RemoveAt(PNODE pNode);
void RemoveAll();
void RemoveHead();
void RemoveTail();

PNODE AddHead(CXList* pNewList);
PNODE AddTail(CXList* pNewList);
PNODE AddHead(TYPE newElement);
PNODE AddTail(TYPE newElement);

BOOL SetAt(PNODE pNode, TYPE newElement);
PNODE InsertBefore(PNODE pNode, TYPE newElement);
PNODE InsertAfter(PNODE pNode, TYPE newElement);
PNODE Find(TYPE searchValue, PNODE pNode=NULL);
PNODE FindIndex(ULONG nIndex);
};

//-----------------------------------------------------------------------------
template<class TYPE>
CXList<TYPE>::CXList()
{

}

template<class TYPE>
CXList<TYPE>::~CXList()
{

}

template<class TYPE>
inline void CXList<TYPE>::_FreeNode(TNode* pNode)
{
m_nCount--;
pNode->data.~TYPE();
if (m_hHeapMem != INVALID_HANDLE_VALUE)
{
if (HeapFree(m_hHeapMem,0,pNode)==TRUE)
{
return;
}
}
MessageBox(NULL,TEXT("_FreeNode failed!"),TEXT("Error"),MB_ICONERROR|MB_OK);
}

template<class TYPE>
inline PNODE CXList<TYPE>::_NewNode(TNode* pPrev, TNode* pNext)
{
if (m_hHeapMem==INVALID_HANDLE_VALUE)
{
m_hHeapMem = HeapCreate(NULL,1024,0);
if (m_hHeapMem==INVALID_HANDLE_VALUE)
{
return NULL;
}
}

TNode *pNode = (TNode*)HeapAlloc(m_hHeapMem,HEAP_ZERO_MEMORY,sizeof(TNode));
if (pNode!=NULL)
{
pNode->pPrev = pPrev;
pNode->pNext = pNext;
if (pPrev!=NULL)
{
pPrev->pNext = pNode;
}
if (pNext!=NULL)
{
pNext->pPrev = pNode;
}
m_nCount++;
}
return pNode;
}

template<class TYPE>
BOOL CXList<TYPE>::Initialize(ULONG nInitSize = 10)
{
m_nCount = 0;
m_hHeapMem = INVALID_HANDLE_VALUE;
m_pNodeHead = NULL;
m_pNodeTail = NULL;
m_pNodeFree = NULL;
m_hHeapMem = HeapCreate(NULL,nInitSize,0);
if (m_hHeapMem==INVALID_HANDLE_VALUE)
{
return FALSE;
}
return TRUE;
}

template<class TYPE>
void CXList<TYPE>::Uninitialize()
{
RemoveAll();
}

template<class TYPE>
TYPE* CXList<TYPE>::operator[](UINT nIndex)
{
TNode* pNode = (TNode*)FindIndex(nIndex);
return &(pNode->data);
}

template<class TYPE>
inline ULONG CXList<TYPE>::GetCount()
{
return m_nCount;
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetHead()
{
return m_pNodeHead==NULL ? NULL : &(m_pNodeHead->data);
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetTail()
{
return m_pNodeTail==NULL ? NULL : &(m_pNodeTail->data);
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetAt(PNODE pNode)
{
TNode* pNODE = (TNode*)pNode;
return pNODE==NULL ? NULL : &(pNODE->data);
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetNext(PNODE pNode)
{
TNode* pNODE = (TNode*)pNode;
if (pNODE != NULL)
{
pNODE = pNODE->pNext;
return pNODE==NULL ? NULL : &(pNODE->data);
}
return NULL;
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetPrev(PNODE pNode)
{
TNode* pNODE = (TNode*)pNode;
if (pNODE != NULL)
{
pNODE = pNODE->pPrev;
return pNODE==NULL ? NULL : &(pNODE->data);
}
return NULL;
}

template<class TYPE>
inline BOOL CXList<TYPE>::IsEmpty()
{
return m_nCount==0 ? TRUE : FALSE;
}

template<class TYPE>
PNODE CXList<TYPE>::AddHead(CXList* pNewList)
{
if (pNewList!=NULL)
{
TNode* pNewNode = NULL;
ULONG nCount = pNewList->GetCount();
for (TNode* pIndex=pNewList->FindIndex(nCount-1); pIndex!=NULL; pIndex=pIndex->pPrev)
{
pNewNode = NULL;
pNewNode = (TNode*)_NewNode(NULL, m_pNodeHead);
if (pNewNode != NULL)
{
pNewNode->data = pIndex->data;
m_pNodeHead = pNewNode;
if (m_pNodeTail==NULL)
{
m_pNodeTail = pNewNode;
}
}
}
}
return m_pNodeHead;
}

template<class TYPE>
PNODE CXList<TYPE>::AddTail(CXList* pNewList)
{
if (pNewList!=NULL)
{
TNode* pNewNode = NULL;
for (TNode* pIndex=pNewList->FindIndex(0); pIndex!=NULL; pIndex=pIndex->pPrev)
{
pNewNode = NULL;
pNewNode = (TNode*)_NewNode(m_pNodeTail, NULL);
if (pNewNode != NULL)
{
pNewNode->data = pIndex->data;
m_pNodeTail = pNewNode;
if (m_pNodeHead==NULL)
{
m_pNodeHead = pNewNode;
}
}
}
}
return m_pNodeTail;
}

template<class TYPE>
PNODE CXList<TYPE>::AddHead(TYPE newElement)
{
TNode* pNewNode = (TNode*)_NewNode(NULL, m_pNodeHead);
if (pNewNode != NULL)
{
pNewNode->data = newElement;
m_pNodeHead = pNewNode;
if (m_pNodeTail==NULL)
{
m_pNodeTail = pNewNode;
}
}
return pNewNode;
}

template<class TYPE>
PNODE CXList<TYPE>::AddTail(TYPE newElement)
{
TNode* pNewNode = (TNode*)_NewNode(m_pNodeTail, NULL);
if (pNewNode != NULL)
{
pNewNode->data = newElement;
m_pNodeTail = pNewNode;
if (m_pNodeHead == NULL)
{
m_pNodeHead = pNewNode;
}
}
return pNewNode;
}

template<class TYPE>
void CXList<TYPE>::RemoveAt(PNODE pNode)
{
if (pNode != NULL)
{
TNode* pNODE = (TNode*)pNode;
TNode* pPrev = pNODE->pPrev;
TNode* pNext = pNODE->pNext;
if (pNODE==m_pNodeHead)
{
m_pNodeHead = m_pNodeHead->pNext;
}
else
{
pPrev->pNext = pNext;
}

if (pNODE==m_pNodeTail)
{
m_pNodeTail = m_pNodeTail->pPrev;
}
else
{
pNext->pPrev = pPrev;
}

_FreeNode(pNODE);
}
}

template<class TYPE>
void CXList<TYPE>::RemoveAll()
{
for (TNode* pIndex=m_pNodeHead; pIndex!=NULL; pIndex=pIndex->pNext)
{
pIndex->data.~TYPE();
}

if (m_hHeapMem != INVALID_HANDLE_VALUE)
{
if (HeapDestroy(m_hHeapMem)==TRUE)
{
m_nCount = 0;
m_pNodeHead = NULL;
m_pNodeTail = NULL;
m_hHeapMem = INVALID_HANDLE_VALUE;
return;
}
}

MessageBox(NULL,TEXT("RemoveAll failed!"),TEXT("Error"),MB_ICONERROR|MB_OK);
}

template<class TYPE>
void CXList<TYPE>::RemoveHead()
{
if (m_pNodeHead != NULL)
{
TNode *pNodeFree = m_pNodeHead;
m_pNodeHead = m_pNodeHead->pNext;
_FreeNode(pNodeFree);
}
else
{
m_pNodeTail = NULL;
}
}

template<class TYPE>
void CXList<TYPE>::RemoveTail()
{
if (m_pNodeTail != NULL)
{
TNode *pNodeFree = m_pNodeTail;
m_pNodeTail = m_pNodeTail->pPrev;
_FreeNode(pNodeFree);
}
else
{
m_pNodeHead = NULL;
}
}

template<class TYPE>
BOOL CXList<TYPE>::SetAt(PNODE pNode, TYPE newElement)
{
if (pNode != NULL)
{
TNode* pNODE = (TNode*)pNode;
pNODE->data = newElement;
return TRUE;
}
return FALSE;
}

template<class TYPE>
PNODE CXList<TYPE>::InsertBefore(PNODE pNode, TYPE newElement)
{
if (pNode!=NULL)
{
TNode* pNODE = (TNode*)pNode;
TNode* pNew = _NewNode(pNODE->pPrev,pNODE);
if (pNew != NULL)
{
pNew->data = newElement;
if (pNew->pPrev==NULL)
{
m_pNodeHead = pNew;
}
return pNew;
}
}
return NULL;
}

template<class TYPE>
PNODE CXList<TYPE>::InsertAfter(PNODE pNode, TYPE newElement)
{
if (pNode!=NULL)
{
TNode* pNODE = (TNode*)pNode;
TNode* pNew = _NewNode(pNODE,pNODE->pNext);
if (pNew != NULL)
{
pNew->data = newElement;
if (pNew->pNext==NULL)
{
m_pNodeTail = pNew;
}
return pNew;
}
}
return NULL;
}

template<class TYPE>
inline PNODE CXList<TYPE>::Find(TYPE searchValue, PNODE pNode)
{
for (TNode* pIndex=m_pNodeHead; pIndex!=NULL; pIndex=pIndex->pNext)
{
if (pIndex->data==searchValue)
{
return pIndex;
}
}
return NULL;
}

template<class TYPE>
inline PNODE CXList<TYPE>::FindIndex(ULONG nIndex)
{
if (nIndex<0 || nIndex>m_nCount)
{
return NULL;
}
else
{
TNode* pIndex = m_pNodeHead;
for (ULONG i=0; i<nIndex; i++)
{
if (pIndex != NULL)
{
pIndex = pIndex->pNext;
}
}
return pIndex;
}
}

...全文
162 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
JiangWenjie2014 2015-06-18
  • 打赏
  • 举报
回复
引用 12 楼 bug1190 的回复:
[quote=引用 8 楼 JiangWenjie2014 的回复:] 话说,把自己造的轮子跟C++ STL中的轮子比较是非常愚蠢的行为。当然了,我并没有否定你,我的建议是,看一下SGI STL版本的list实现,然后按它的样子改一份你自己的版本,保证让你受益匪浅。还有在这个版本的STL中如果分配的空间小于512byte,从内存池中去,否则直接operator new申请内存。
为什么不能比? 第一:我的代码里没有什么迭代器的东东,想用就直接用,简洁,第二:我的代码是在堆上分配的,申请,回收速度快,不服自己测,new的内部调用的是malloc分配的,malloc分配的内存是不提供诸多的内存管理特性的,典型的如,内存块是否可以移动,大量小块内存造成的碎片等,至少哥哥我的在堆上统一分配的全部都是固定块,第一不用锁,第二全部统一SIZE块,所以就消除了碎片,明白?[/quote] 哈哈,要说代码简洁,你再怎么精简,会比linux kernel list简洁?标准库之所以用malloc,是因为malloc也是标准中的东西,你的Heap API能在非Win平台下用?况且,STL中的list模板类,第二个模板参数是Allocator,你知道Allocator是干嘛的吗?它就是申请内存的东西,你看看标准库中的list把跟内存有关的操作(申请释放)都独立出一个类来:

template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class list;
所以如果你嫌弃malloc的话,完全可以定制你自己的Allocator,比如名字叫MyHeapAlloc,然后这么使用:

std::list <SomeType, MyHeapAlloc <SomeType> > mylist;
现在你明白我的意思了吧,你想到的,其实别人都已经仔细考虑过了。
huanglin03 2015-06-18
  • 打赏
  • 举报
回复
引用 8 楼 JiangWenjie2014 的回复:
话说,把自己造的轮子跟C++ STL中的轮子比较是非常愚蠢的行为。当然了,我并没有否定你,我的建议是,看一下SGI STL版本的list实现,然后按它的样子改一份你自己的版本,保证让你受益匪浅。还有在这个版本的STL中如果分配的空间小于512byte,从内存池中去,否则直接operator new申请内存。
为什么不能比? 第一:我的代码里没有什么迭代器的东东,想用就直接用,简洁,第二:我的代码是在堆上分配的,申请,回收速度快,不服自己测,new的内部调用的是malloc分配的,malloc分配的内存是不提供诸多的内存管理特性的,典型的如,内存块是否可以移动,大量小块内存造成的碎片等,至少哥哥我的在堆上统一分配的全部都是固定块,第一不用锁,第二全部统一SIZE块,所以就消除了碎片,明白?
huanglin03 2015-06-18
  • 打赏
  • 举报
回复
引用 9 楼 storyhare 的回复:
最后,STL中的list可以使用内存池,其分配速度更快(一次分配大量内存);所以,你的版本不见得会更快。 STL中的迭代器,是内部标准,兼容各种STL算法;能够得到很多操作支持。(当然,没有提供随机访问); 但你版本中的operator[],是线性访问,在实际中;有着极大的速度限制。 综上,因为有BUG;所以没能测试速度; 但我个人认为,不见得很快;特别是在STL版本使用内存池后。
先谢谢兄弟帮我测试,但你说提供随机访问啊,又说我的operator[],是线性访问啊,有速度限制啊,我想说的是:你根本没搞清楚状况!哥哥我这实现的是链表,不是数组!链表的优势就是插入,删除快速,想做到随机访问,那就不叫链表了!!!明白,只有数组能提供随机访问,但数组的缺点就是插入,删除都有数据搬移的动作,所以就是访问快,增删慢,是不可能有人把这两种数据结构结合成一种更优的,所以你说链表提供随机访问,说哥的operator[]是线性访问,简直就是扯淡!!!翻翻大学里的数据结构的书吧,骚年
huanglin03 2015-06-18
  • 打赏
  • 举报
回复
引用 7 楼 storyhare 的回复:
以及,链表没有定义复制构造函数,以及赋值函数;但也没有拒绝,编译器会自动生成浅复制的版本; 这样是极其不安全的,你的版本中似乎没有解决.......
兄弟,不得不说,你说到了几个关键的问题,就是对象的赋值操作和比较操作符的重载问题,你提的这个问题提的好,但我的回答是:作为一个写模板的人来讲,没必要考虑对象是否支持赋值运算符和比较运算符的,这是模板参数类应该负责完成的事情,本来我在这里想用MemoryCopy来完成的,但后来放弃了------你去看看有哪个模板类保证了你的赋值操作和比较操作是安全的!没有一个这样干,这一部分完全不应该做进模板类中去保证,而应该是什么类型就由什么类型来保证,所以你考虑的还是不全
storyhare 2015-06-18
  • 打赏
  • 举报
回复
引用 10 楼 bug1190 的回复:
兄弟,不得不说,你说到了几个关键的问题,就是对象的赋值操作和比较操作符的重载问题,你提的这个问题提的好,但我的回答是:作为一个写模板的人来讲,没必要考虑对象是否支持赋值运算符和比较运算符的,这是模板参数类应该负责完成的事情,本来我在这里想用MemoryCopy来完成的,但后来放弃了------你去看看有哪个模板类保证了你的赋值操作和比较操作是安全的!没有一个这样干,这一部分完全不应该做进模板类中去保证,而应该是什么类型就由什么类型来保证,所以你考虑的还是不全
我说了2个赋值操作: 1、TYPE的“operator=”;你的链表中分配内存后没有构造,便直接使用赋值操作;是不安全的,没有构造的对象,对其的任何操作,都是未定义的非安全访问。 2、CXList链表本身的“operator=”;你没有定义,但也没有拒绝;当CXList对象复制或赋值时,使用的是浅复制,是极不安全的。 另外,MemoryCopy,也是极不安全的;因为非POD对象的复制,是不能够直接复制内存的;必须逐个构造。
FightForProgrammer 2015-06-17
  • 打赏
  • 举报
回复
storyhare 2015-06-17
  • 打赏
  • 举报
回复
最后,STL中的list可以使用内存池,其分配速度更快(一次分配大量内存);所以,你的版本不见得会更快。 STL中的迭代器,是内部标准,兼容各种STL算法;能够得到很多操作支持。(当然,没有提供随机访问); 但你版本中的operator[],是线性访问,在实际中;有着极大的速度限制。 综上,因为有BUG;所以没能测试速度; 但我个人认为,不见得很快;特别是在STL版本使用内存池后。
JiangWenjie2014 2015-06-17
  • 打赏
  • 举报
回复
话说,把自己造的轮子跟C++ STL中的轮子比较是非常愚蠢的行为。当然了,我并没有否定你,我的建议是,看一下SGI STL版本的list实现,然后按它的样子改一份你自己的版本,保证让你受益匪浅。还有在这个版本的STL中如果分配的空间小于512byte,从内存池中去,否则直接operator new申请内存。
storyhare 2015-06-17
  • 打赏
  • 举报
回复
以及,链表没有定义复制构造函数,以及赋值函数;但也没有拒绝,编译器会自动生成浅复制的版本; 这样是极其不安全的,你的版本中似乎没有解决.......
storyhare 2015-06-17
  • 打赏
  • 举报
回复
另外问一下,链表添加对象时,是在哪里构造的;因为是用堆分配的原始内存,没有构造前,是不能够安全地运行赋值操作:
pNewNode->data = newElement;
当然,我可能看漏了.....
storyhare 2015-06-17
  • 打赏
  • 举报
回复
测试了一下,在VS2013与Dev-c++上通过编译;但运行出错(addHead(TYPE)内存访问出错)...... 也就是,有BUG,无法运行的.....
shiguojie19892 2015-06-17
  • 打赏
  • 举报
回复
好长啊
huanglin03 2015-06-17
  • 打赏
  • 举报
回复
修改了一点代码,完美版:

//--------------------------------------------------------------------------------------------------------------------------------

#pragma once

typedef void* PNODE;

template<class TYPE> 
class CXList
{	
protected:
	struct TNode{TNode* pNext;TNode* pPrev;TYPE data;};
	ULONG  m_nCount;
	HANDLE m_hHeapMem;
	TNode* m_pNodeHead;
	TNode* m_pNodeTail;
	
protected:
	void _FreeNode(TNode* pNode);
	PNODE _NewNode(TNode* pPrev, TNode* pNext);

public:
	CXList();
	~CXList();
	BOOL Initialize(ULONG nInitSize = 10);
	void Uninitialize();

	ULONG GetCount();
	TYPE* GetHead();
	TYPE* GetTail();
	TYPE* GetAt(PNODE pNode);
	TYPE* GetNext(PNODE pNode);
	TYPE* GetPrev(PNODE pNode);
	TYPE* operator[](UINT nIndex);

	BOOL IsEmpty();
	void RemoveAt(PNODE pNode);
	void RemoveAll();
	void RemoveHead();
	void RemoveTail();

	PNODE AddHead(CXList* pNewList);
	PNODE AddTail(CXList* pNewList);
	PNODE AddHead(TYPE newElement);
	PNODE AddTail(TYPE newElement);

	BOOL SetAt(PNODE pNode, TYPE newElement);
	PNODE InsertBefore(PNODE pNode, TYPE newElement);
	PNODE InsertAfter(PNODE pNode, TYPE newElement);
	PNODE Find(TYPE searchValue, PNODE pNode=NULL);
	PNODE FindIndex(ULONG nIndex);
};

//---------------------------------------------------------------------------------------------------------------
template<class TYPE>
CXList<TYPE>::CXList()
{
	
}

template<class TYPE>
CXList<TYPE>::~CXList()
{	
	
}

template<class TYPE>
inline void CXList<TYPE>::_FreeNode(TNode* pNode)
{
	pNode->data.~TYPE();
	if (m_hHeapMem != INVALID_HANDLE_VALUE)
	{
		if (HeapFree(m_hHeapMem,0,pNode)==TRUE)
		{
			m_nCount--;
			m_nCount = min(m_nCount,0);
			return;
		}
	}
	MessageBox(NULL,TEXT("_FreeNode failed!"),TEXT("Error"),MB_ICONERROR|MB_OK);
}

template<class TYPE>
inline PNODE CXList<TYPE>::_NewNode(TNode* pPrev, TNode* pNext)
{	
	if (m_hHeapMem==INVALID_HANDLE_VALUE)
	{
		m_hHeapMem = HeapCreate(NULL,1024,0);
		if (m_hHeapMem==INVALID_HANDLE_VALUE)
		{
			return NULL;
		}
	}

	TNode *pNode = (TNode*)HeapAlloc(m_hHeapMem,HEAP_ZERO_MEMORY,sizeof(TNode));
	if (pNode!=NULL)
	{	
		pNode->pPrev = pPrev;
		pNode->pNext = pNext;
		if (pPrev!=NULL)
		{
			pPrev->pNext = pNode;
		}
		if (pNext!=NULL)
		{
			pNext->pPrev = pNode;
		}
		m_nCount++;
	}
	return pNode;
}

template<class TYPE>
BOOL CXList<TYPE>::Initialize(ULONG nInitSize = 10)
{	
	m_nCount	 = 0;
	m_hHeapMem	 = INVALID_HANDLE_VALUE;
	m_pNodeHead	 = NULL;
	m_pNodeTail	 = NULL;
	m_hHeapMem   = HeapCreate(NULL,nInitSize,0);
	if (m_hHeapMem==INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}
	return TRUE;
}

template<class TYPE>
void CXList<TYPE>::Uninitialize()
{
	RemoveAll();
}

template<class TYPE>
inline ULONG CXList<TYPE>::GetCount()
{
	return m_nCount;
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetHead()
{
	return m_pNodeHead==NULL ? NULL : &(m_pNodeHead->data);
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetTail()
{
	return m_pNodeTail==NULL ? NULL : &(m_pNodeTail->data);
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetAt(PNODE pNode)
{
	TNode* pNODE = (TNode*)pNode;
	return pNODE==NULL ? NULL : &(pNODE->data);
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetNext(PNODE pNode)
{
	TNode* pNODE = (TNode*)pNode;
	if (pNODE != NULL)
	{
		pNODE = pNODE->pNext;
		return pNODE==NULL ? NULL : &(pNODE->data);
	}
	return NULL;
}

template<class TYPE>
inline TYPE* CXList<TYPE>::GetPrev(PNODE pNode)
{
	TNode* pNODE = (TNode*)pNode;
	if (pNODE != NULL)
	{
		pNODE = pNODE->pPrev;
		return pNODE==NULL ? NULL : &(pNODE->data);
	}
	return NULL;
}

template<class TYPE>
TYPE* CXList<TYPE>::operator[](UINT nIndex)
{
	TNode* pNode = (TNode*)FindIndex(nIndex);
	return pNode==NULL ? NULL : &(pNode->data);
}

template<class TYPE>
inline BOOL CXList<TYPE>::IsEmpty()
{
	return m_nCount==0 ? TRUE : FALSE;
}

template<class TYPE>
PNODE CXList<TYPE>::AddHead(CXList* pNewList)
{	
	if (pNewList!=NULL)
	{
		TNode* pNewNode = NULL;
		ULONG nCount = pNewList->GetCount();
		for (TNode* pIndex=pNewList->FindIndex(nCount-1); pIndex!=NULL; pIndex=pIndex->pPrev)
		{
			pNewNode = NULL;
			pNewNode = (TNode*)_NewNode(NULL, m_pNodeHead);
			if (pNewNode != NULL)
			{	
				pNewNode->data = pIndex->data;
				m_pNodeHead = pNewNode;
				if (m_pNodeTail==NULL)
				{
					m_pNodeTail = pNewNode;
				}
			}
		}
	}
	return m_pNodeHead;
}

template<class TYPE>
PNODE CXList<TYPE>::AddTail(CXList* pNewList)
{	
	if (pNewList!=NULL)
	{	
		TNode* pNewNode = NULL;
		for (TNode* pIndex=pNewList->FindIndex(0); pIndex!=NULL; pIndex=pIndex->pPrev)
		{
			pNewNode = NULL;
			pNewNode = (TNode*)_NewNode(m_pNodeTail, NULL);
			if (pNewNode != NULL)
			{
				pNewNode->data = pIndex->data;
				m_pNodeTail = pNewNode;
				if (m_pNodeHead==NULL)
				{
					m_pNodeHead = pNewNode;
				}
			}
		}
	}
	return m_pNodeTail;
}

template<class TYPE>
PNODE CXList<TYPE>::AddHead(TYPE newElement)
{	
	TNode* pNewNode = (TNode*)_NewNode(NULL, m_pNodeHead);
	if (pNewNode != NULL)
	{
		pNewNode->data = newElement;
		m_pNodeHead = pNewNode;
		if (m_pNodeTail==NULL)
		{
			m_pNodeTail = pNewNode;
		}
	}
	return pNewNode;
}

template<class TYPE>
PNODE CXList<TYPE>::AddTail(TYPE newElement)
{
	TNode* pNewNode = (TNode*)_NewNode(m_pNodeTail, NULL);
	if (pNewNode != NULL)
	{
		pNewNode->data = newElement;
		m_pNodeTail = pNewNode;
		if (m_pNodeHead == NULL)
		{
			m_pNodeHead = pNewNode;
		}
	}
	return pNewNode;
}

template<class TYPE> 
void CXList<TYPE>::RemoveAt(PNODE pNode)
{	
	if (pNode != NULL)
	{	
		TNode* pNODE = (TNode*)pNode;
		TNode* pPrev = pNODE->pPrev;
		TNode* pNext = pNODE->pNext;

		if (m_pNodeHead==pNODE)
		{
			m_pNodeHead = m_pNodeHead->pNext;
		}
		else
		{
			pPrev->pNext = pNext;
		}

		if (m_pNodeTail==pNODE)
		{
			m_pNodeTail = m_pNodeTail->pPrev;
		}
		else
		{
			pNext->pPrev = pPrev;
		}
		
		_FreeNode(pNODE);
	}
}

template<class TYPE>
void CXList<TYPE>::RemoveAll()
{	
	for (TNode* pIndex=m_pNodeHead; pIndex!=NULL; pIndex=pIndex->pNext)
	{
		pIndex->data.~TYPE();
	}
	
	if (m_hHeapMem != INVALID_HANDLE_VALUE)
	{
		if (HeapDestroy(m_hHeapMem)==TRUE)
		{
			m_nCount    = 0;
			m_pNodeHead = NULL;
			m_pNodeTail = NULL;
			m_hHeapMem  = INVALID_HANDLE_VALUE;
			return;
		}
	}

	MessageBox(NULL,TEXT("RemoveAll failed!"),TEXT("Error"),MB_ICONERROR|MB_OK);
}

template<class TYPE>
void CXList<TYPE>::RemoveHead()
{
	if (m_pNodeHead != NULL)
	{
		TNode *pNodeFree = m_pNodeHead;
		m_pNodeHead = m_pNodeHead->pNext;
		if (m_pNodeHead==NULL)
		{
			m_pNodeTail = NULL;
		}
		_FreeNode(pNodeFree);
	}
}

template<class TYPE>
void CXList<TYPE>::RemoveTail()
{
	if (m_pNodeTail != NULL)
	{
		TNode *pNodeFree = m_pNodeTail;
		m_pNodeTail = m_pNodeTail->pPrev;
		if (m_pNodeTail==NULL)
		{
			m_pNodeHead = NULL;
		}
		_FreeNode(pNodeFree);
	}
}

template<class TYPE>
BOOL CXList<TYPE>::SetAt(PNODE pNode, TYPE newElement)
{
	if (pNode != NULL)
	{
		TNode* pNODE = (TNode*)pNode;
		pNODE->data = newElement;
		return TRUE;
	}
	return FALSE;
}

template<class TYPE>
PNODE CXList<TYPE>::InsertBefore(PNODE pNode, TYPE newElement)
{	
	if (pNode!=NULL)
	{	
		TNode* pNODE = (TNode*)pNode;
		TNode* pNew = _NewNode(pNODE->pPrev,pNODE);
		if (pNew != NULL)
		{	
			pNew->data = newElement;
			if (pNew->pPrev==NULL)
			{
				m_pNodeHead = pNew;
			}
			return pNew;
		}
	}
	return NULL;
}

template<class TYPE>
PNODE CXList<TYPE>::InsertAfter(PNODE pNode, TYPE newElement)
{
	if (pNode!=NULL)
	{	
		TNode* pNODE = (TNode*)pNode;
		TNode* pNew = _NewNode(pNODE,pNODE->pNext);
		if (pNew != NULL)
		{
			pNew->data = newElement;
			if (pNew->pNext==NULL)
			{
				m_pNodeTail = pNew;
			}
			return pNew;
		}
	}
	return NULL;
}

template<class TYPE>
inline PNODE CXList<TYPE>::Find(TYPE searchValue, PNODE pNode)
{
	for (TNode* pIndex=m_pNodeHead; pIndex!=NULL; pIndex=pIndex->pNext)
	{
		if (pIndex->data==searchValue)
		{
			return pIndex;
		}
	}
	return NULL;
}

template<class TYPE>
inline PNODE CXList<TYPE>::FindIndex(ULONG nIndex)
{
	if (nIndex>=0 && nIndex<m_nCount)
	{
		TNode* pIndex = m_pNodeHead;
		for (UINT i=0; i<nIndex && pIndex!=NULL; i++)
		{
			pIndex = pIndex->pNext;
		}
		return pIndex;
	}
	return NULL;
}

weixin_29060033 2015-06-17
  • 打赏
  • 举报
回复
先收藏,有空看

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧