自己的底层代码库(一)——单链表

来源:互联网 发布:网络写手哪个网站好 编辑:程序博客网 时间:2024/04/28 22:57

开头先介绍下背景,本人是做游戏服务器端开发的,最近项目不紧,所以一直计划着完善自己的一套底层代码库,包括容器,内存池,智能指针,网络,数据库等等。并在此基础上完成一个C/S的服务器设计。


顺便提一句,后续的这些代码,在可能的情况下,基本上都是采取空间换时间的思路,比如很多地方会在设计的时候多记录几个指针,达到更快的获取而不用搜索的目的。


今天是第一篇,最基础的单链表,实现的其实是队列的功能。

这里就没有实现单链表的中途插入和删除操作了,因为单链表的中途删除,需要遍历,效率不是很高,因此就不提供了,下篇的双链表中再实现这两个功能。


PS:

2013.6.5修改了容器的实现:继承了后面提到的TContainer,实现相关接口。


上代码:

#ifndef _TLinkList_h_#define _TLinkList_h_#include <windows.h>#include "TContainer.h"template <class T>class TLinkList;//单向链表结点template <class T>struct TLinker{TLinker<T> *m_pNext;//下一个结点T m_Value;//值域};//单向链表//该类自己不申请TLinker,只是负责管理外部申请的TLinker结点//将其链表化,提供接入、删除功能template <class T>class TLinkList : public TContainer<T>{public:TLinkList();~TLinkList();//将pLinker加入到链表尾//成功返回true//参数不合法返回falsebool PushTail(TLinker<T> *pLinker);//从链表头拿一个pLinker出来,从链表中断开pLinker//成功返回pLinker//链表本身没有结点了返回NULLTLinker<T> *PopHead();// 初始化\清空链表void Init(ContainerFlag dwLock = enum_EnableLock);//获取链表头对象//若m_pHead为空则返回空T *GetHead();//获取链表中curr的下一个对象//若curr为空则返回空//若curr没有下一个对象则返回空T *GetNext(T *curr);//获取链表中curr对应的结点对象//若curr为空则返回空void *GetNode(T *curr);private:TLinker<T> *m_pHead;//头指针TLinker<T> *m_pTail;//尾指针};#include "TLinkList.hpp"#endif


说明:

1、此处TLinker结构里面没有做成T *m_Value,而是让数据直接包含在结点中(数据就是指针的另算),一个是可以省四字节的指针空间;二主要是为了方便,当在逻辑当中知道某个对象的物理地址的时候,可以直接根据该对象的地址(T的地址)计算出结点的地址(TLinker的地址),这样提供给逻辑的指针,可以直接是T的地址,而不需要暴露整个TLinker结构给上层逻辑。比如上层逻辑有一个Obj a,但是不知道a对应的链表结点,当需要在TLinkList<Obj> listA上操作a对象的时候,就得遍历链表,逐个判断找出a对应的TLinker,再操作。但是现在不需要遍历了,写一个宏,可以计算出TLinker了,

#define MemOffset(ClassName, MemberName) \((DWORD)(&(((ClassName *)0)->MemberName)))#define ContainerOf(MemberAddr , ClassName , MemberName) \((ClassName *)((DWORD)(MemberAddr) - MemOffset(ClassName , MemberName)))

那么结点的地址就是:TLinker<Obj> *pLinker = ContainerOf(&a, TLinker<Obj>, m_Value);

2、PushTail的参数的安全性,此处只检查了pLinker是否为空,没有对pLinker的从属做检查,也就是没有判断pLinker是否已经在这个链表上了,这是使用时需要注意的,必须明确PushTail传递的结点,不是之前应经被Push但是没有Pop出来的结点。在下篇的双向链表中,双向链表的结点的设计会加上结点从属链表对象的字段。



最后贴下实现TLinkList.hpp

#ifndef _TLinkList_hpp_#define _TLinkList_hpp_template <class T>TLinkList<T>::TLinkList(){Init();}template <class T>TLinkList<T>::~TLinkList(){Init();}template <class T>void TLinkList<T>::Init(ContainerFlag dwLock){m_pHead = NULL;m_pTail = NULL;m_dwLen = 0;m_dwLock = dwLock;}template <class T>TLinker<T> *TLinkList<T>::PopHead(){TLinker<T> *pLinker = NULL;//此处需要在下面if的外面加锁//因为m_pHead在多线程环境下可能会变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;if (m_pTail == pLinker){m_pTail = NULL;}m_dwLen--;}if (enum_EnableLock == m_dwLock){m_csLock.UnLock();}return pLinker;}template <class T>bool TLinkList<T>::PushTail(TLinker<T> *pLinker){bool bRes = false;if (NULL != pLinker){if (enum_EnableLock == m_dwLock){m_csLock.Lock();}pLinker->m_pNext = NULL;if (NULL != m_pTail){m_pTail->m_pNext = pLinker;}m_pTail = pLinker;if (NULL == m_pHead){m_pHead = pLinker;}m_dwLen++;if (enum_EnableLock == m_dwLock){m_csLock.UnLock();}bRes = true;}return bRes;}template <class T>T *TLinkList<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>T *TLinkList<T>::GetNext(T *curr){T *pRes = NULL;if (NULL != curr){if (enum_EnableLock == m_dwLock){m_csLock.Lock();}TLinker<T> *pCurrLinker = (TLinker<T> *)GetNode(curr);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 *TLinkList<T>::GetNode(T *curr){TLinker<T> *pRes = NULL;if (NULL != curr){pRes = ContainerOf(curr, TLinker<T>, m_Value);}return pRes;}#endif