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

开头先介绍下背景,本人是做游戏服务器端开发的,最近项目不紧,所以一直计划着完善自己的一套底层代码库,包括容器,内存池,智能指针,网络,数据库等等。并在此基础上完成一个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
	//参数不合法返回false
	bool PushTail(TLinker<T> *pLinker);

	//从链表头拿一个pLinker出来,从链表中断开pLinker
	//成功返回pLinker
	//链表本身没有结点了返回NULL
	TLinker<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



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值