今天放上双链表的实现
PS:
2013.6.5修改了容器的实现:继承了后面提到的TContainer,实现相关接口。
链表的定义TBDLinkList.h:
#ifndef _TBDLinkList_h_
#define _TBDLinkList_h_
#include <windows.h>
#include "TContainer.h"
template <class T>
class TBDLinkList;
//双向链表结点
template <class T>
struct TBDLinker
{
TBDLinker<T> *m_pLast; //上一个结点
TBDLinker<T> *m_pNext; //下一个结点
TBDLinkList<T> *m_pLinkList;//该结点当前从属的链表
T m_Value; //值域
void Init()
{
m_pLast = NULL;
m_pNext = NULL;
m_pLinkList = NULL;
}
};
//双向链表
//该类自己不申请TBDLinker,只是负责管理外部申请的TBDLinker结点
//将其链表化,提供插入、删除功能
template <class T>
class TBDLinkList : public TContainer<T>
{
public:
TBDLinkList();
~TBDLinkList();
//将pLinker加入到链表尾
//放入结点时将对pLinker的m_pLinkList赋值this
//成功返回true
//参数不合法,返回false
//pLinker本身已经有从属链表(m_pLinkList不为NULL)返回false
bool PushTail(TBDLinker<T> *pLinker);
//将pLinker接在pLaster的后面
//放入结点时将对pLinker的m_pLinkList赋值this
//成功返回true
//参数不合法,返回false
//pLaster不属于当前链表返回false
//pLinker本身已经有从属链表(m_pLinkList不为NULL)返回false
bool InsertAsNext(TBDLinker<T> *pLaster, TBDLinker<T> *pLinker);
//将pLinker接在pNexter的前面
//放入结点时将对pLinker的m_pLinkList赋值this
//成功返回true
//参数不合法,返回false
//pNexter不属于当前链表返回false
//pLinker本身已经有从属链表(m_pLinkList不为NULL)返回false
bool InsertAsLast(TBDLinker<T> *pLinker, TBDLinker<T> *pNexter);
//从链表头拿一个pLinker出来,链表中删除pLinker
//取出结点时pLinker的m_pLinkList将被置空
//成功返回pLinker
//链表本身没有结点了返回NULL
TBDLinker<T> *PopHead();
//在链表中断开pLinker
//断开结点时pLinker的m_pLinkList将被置空
//成功返回true
//参数不合法,返回false
//结点不属于当前链表返回false
bool Remove(TBDLinker<T> *pLinker);
//初始化\清空链表
void Init(ContainerFlag dwLock = enum_EnableLock);
//获取链表头对象
//若m_pHead为空则返回空
T *GetHead();
//获取链表头
//若m_pHead为空则返回空
TBDLinker<T> *GetHeadNode();
//获取链表中curr的下一个对象
//若curr为空则返回空
//若curr不属于当前链表则返回空
//若curr没有下一个对象则返回空
T *GetNext(T *curr);
//获取链表中curr对应的结点对象
//若curr为空则返回空
//PS:该函数不区分curr是否属于当前链表
void *GetNode(T *curr);
private:
TBDLinker<T> *m_pHead;//头指针
TBDLinker<T> *m_pTail;//尾指针
};
#include "TBDLinkList.hpp"
#endif
该类设计思路与之前的单链表大致相同,需要再说明的两点:
1、增加了一个 “结点当前从属的链表”字段m_pLinkList,(1)是用来对插入链表的结点的合法性做检查,当你要插入的结点实际上已经在该链表上的时候,通过该字段的验证可以排除这种情况。(2)是当逻辑中存在多个链表对象来管理结点的情况下,比如有3个链表list1,list2,list3分别表示3种不同状态的队列,结点node会在这3个队列中(也就是在3种状态间)切换的时候,m_pLinkList可以明确的指出node当前属于哪一个队列上,或者不属于任何一个队列,不需要为了确定该结点在什么地方而做遍历。
2、结点中T m_Value的设计,当出现T需要由不用容器同时来管理的时候,比如T,在T的对象池中,空闲对象的队列希望由单链表来管理(插入删除方便),使用中对象的队列希望由AVL树来管理(查找快一点),该怎么办。这时采用的就是模版的嵌套来解决,比如 TLinker<TreeNode<T>>。
实现TBDLinkList.hpp
#ifndef _TBDLinkList_hpp_
#define _TBDLinkList_hpp_
template <class T>
TBDLinkList<T>::TBDLinkList()
{
Init();
}
template <class T>
TBDLinkList<T>::~TBDLinkList()
{
Init();
}
template <class T>
void TBDLinkList<T>::Init(ContainerFlag dwLock)
{
m_pHead = NULL;
m_pTail = NULL;
m_dwLen = 0;
m_dwLock = dwLock;
}
template <class T>
bool TBDLinkList<T>::PushTail(TBDLinker<T> *pLinker)
{
bool bRes = false;
if (NULL != pLinker)
{
//此处需要在下面if的外面加锁
//因为pLinker->m_pLinkList在多线程环境下可能会变
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
if (NULL == pLinker->m_pLinkList)
{
pLinker->m_pLast = m_pTail;
pLinker->m_pNext = NULL;
pLinker->m_pLinkList = this;
if (NULL != m_pTail)
{
m_pTail->m_pNext = pLinker;
}
m_pTail = pLinker;
if (NULL == m_pHead)
{
m_pHead = pLinker;
}
m_dwLen++;
bRes = true;
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
}
return bRes;
}
template <class T>
bool TBDLinkList<T>::InsertAsNext(TBDLinker<T> *pLaster, TBDLinker<T> *pLinker)
{
bool bRes = false;
if (NULL != pLinker && NULL != pLinker)
{
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
if (this == pLaster->m_pLinkList && NULL == pLinker->m_pLinkList)
{
pLinker->m_pLast = pLaster;
pLinker->m_pNext = pLaster->m_pNext;
pLaster->m_pNext = pLinker;
if (NULL != pLinker->m_pNext)
{
pLinker->m_pNext->m_pLast = pLinker;
}
pLinker->m_pLinkList = this;
if (pLaster == m_pTail)
{
m_pTail = pLinker;
}
m_dwLen++;
bRes = true;
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
}
return bRes;
}
template <class T>
bool TBDLinkList<T>::InsertAsLast(TBDLinker<T> *pLinker, TBDLinker<T> *pNexter)
{
bool bRes = false;
if (NULL != pLinker && NULL != pLinker)
{
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
if (this == pNexter->m_pLinkList && NULL == pLinker->m_pLinkList)
{
pLinker->m_pNext = pNexter;
pLinker->m_pLast = pNexter->m_pLast;
pNexter->m_pLast = pLinker;
if (NULL != pLinker->m_pLast)
{
pLinker->m_pLast->m_pNext = pLinker;
}
pLinker->m_pLinkList = this;
if (pNexter == m_pHead)
{
m_pHead = pLinker;
}
m_dwLen++;
bRes = true;
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
}
return bRes;
}
template <class T>
TBDLinker<T> *TBDLinkList<T>::PopHead()
{
TBDLinker<T> *pLinker = NULL;
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
if (NULL != m_pHead)
{
pLinker = m_pHead;
ResetNext(&(pLinker->m_Value));
m_pHead = m_pHead->m_pNext;
pLinker->m_pNext = NULL;
pLinker->m_pLast = NULL;
pLinker->m_pLinkList = NULL;
if (m_pTail == pLinker)
{
m_pTail = NULL;
}
if (NULL != m_pHead)
{
m_pHead->m_pLast = NULL;
}
m_dwLen--;
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
return pLinker;
}
template <class T>
bool TBDLinkList<T>::Remove(TBDLinker<T> *pLinker)
{
bool bRes = false;
if (NULL != pLinker)
{
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
if (this == pLinker->m_pLinkList)
{
ResetNext(&(pLinker->m_Value));
if (m_pHead == pLinker)
{
m_pHead = pLinker->m_pNext;
}
if (m_pTail == pLinker)
{
m_pTail = pLinker->m_pLast;
}
if (NULL != pLinker->m_pNext)
{
pLinker->m_pNext->m_pLast = pLinker->m_pLast;
}
if (NULL != pLinker->m_pLast)
{
pLinker->m_pLast->m_pNext = pLinker->m_pNext;
}
pLinker->m_pNext = NULL;
pLinker->m_pLast = NULL;
pLinker->m_pLinkList = NULL;
m_dwLen--;
bRes = true;
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
}
return bRes;
}
template <class T>
T *TBDLinkList<T>::GetHead()
{
T *pRes = NULL;
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
if (NULL != m_pHead)
{
pRes = &(m_pHead->m_Value);
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
return pRes;
}
template <class T>
TBDLinker<T> *TBDLinkList<T>::GetHeadNode()
{
return m_pHead;
}
template <class T>
T *TBDLinkList<T>::GetNext(T *curr)
{
T *pRes = NULL;
if (NULL != curr)
{
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
TBDLinker<T> *pCurrLinker = (TBDLinker<T> *)GetNode(curr);
if (this == pCurrLinker->m_pLinkList)
{
if (NULL != pCurrLinker->m_pNext)
{
pRes = &(pCurrLinker->m_pNext->m_Value);
}
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
}
return pRes;
}
template <class T>
void *TBDLinkList<T>::GetNode(T *curr)
{
TBDLinker<T> *pRes = NULL;
if (NULL != curr)
{
pRes = ContainerOf(curr, TBDLinker<T>, m_Value);
}
return pRes;
}
#endif