自己写的LinkList

Source FILE: CAlgCommon.h

#ifndef _C_ALG_COMMON_H_
#define _C_ALG_COMMON_H_
#include <string.h>
#include <stdlib.h>


#ifndef __cplusplus
#define inline __inline
#endif


#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
	CALG_ENUM_NEXT = 0,
	CALG_ENUM_REPEAT ,
	CALG_ENUM_STOP 
}CAlgEnum;


typedef CAlgEnum (*Alg_IteRator_F)(void* elem);
typedef int (*Alg_Cmp_F)(const void* left, const void* right, unsigned int size);


#ifdef __cplusplus
}
#endif


#endif
//end of file

Source File: CAlgList.h

#ifndef _C_ALG_LIST_H_
#define _C_ALG_LIST_H_
#include <string.h>
#include <stdlib.h>
#include "CAlgCommon.h"


#ifdef __cplusplus
extern "C" {
#endif


typedef struct _CAlgNode{
	void * curr_data;
	
	struct _CAlgNode * prev;
struct _CAlgNode * next;
}CAlgNode;

typedef struct {
	CAlgNode* head;
	CAlgNode* tail;
	int elem_count;
	unsigned int elem_size;
}CAlgList;

static inline void CAlgList_ReSet(CAlgList* l, unsigned int elem_size)
{
	l->head = l->tail = NULL;
	l->elem_count = 0;
	l->elem_size = elem_size;
}

static inline void CAlgList_Insert(CAlgList* l, CAlgNode* prev, CAlgNode* n)
{
	n->prev = prev;	
	if(prev)
	{
		n->next = prev->next;
		prev->next = n;
	}
	else
	{
		n->next = l->head;
		l->head = n;
	}
	if(n->next)
		n->next->prev = n;
	if(prev == l->tail)
		l->tail = n;
	l->elem_count ++;
}

static inline CAlgNode* CAlgList_AddHead(CAlgList* l, CAlgNode* n)
{
	CAlgList_Insert(l, NULL, n);
	return l->head;
}

static inline CAlgNode* CAlgList_AddTail(CAlgList* l, CAlgNode* n)
{
	CAlgList_Insert(l, l->tail, n);
	return l->tail;
}

static inline CAlgNode* CAlgList_Find(CAlgList* l, void* data, Alg_Cmp_F node_cmp)
{
	CAlgNode* tmp = l->head;
	if(node_cmp == NULL)
	node_cmp = memcmp;
	while(tmp)
	{
		if(0 == node_cmp(tmp->curr_data, data, l->elem_size))
			return tmp;
		tmp = tmp->next;
	}
	return NULL;
}

static inline int CAlgList_RemoveNode(CAlgList* l, CAlgNode* n)
{
	if( NULL == n) return -1;
	if(n == l->head)
		l->head = l->head->next;
	if(n == l->tail)
		l->tail = l->tail->prev;
	if(n->prev)
		n->prev->next = n->next;
	if(n->next)
		n->next->prev = n->prev;
	if(n)
		l->elem_count --;
	return 0;
}

static inline CAlgNode* CAlgList_RemoveHead(CAlgList* l)
{
	CAlgNode* head = l->head;
	CAlgList_RemoveNode(l, l->head);
	return head;
}

static inline CAlgNode* CAlgList_RemoveTail(CAlgList* l)
{
	CAlgNode* tail = l->tail;
	CAlgList_RemoveNode(l, l->tail);
	return tail;
}

#define ALGLIST_FOREACH(alglist, node) do{\
node = alglist->head;\
for(; NULL != node; node=node->next){

#define ALGLIST_FOREACH_END() }}while(0);

static inline int CAlgList_Enum(const CAlgList* l, Alg_IteRator_F it, int reverse)
{
	int count = 0u;
	CAlgNode* tmp ;
	CAlgEnum rc ;
	if(reverse)
		tmp = l->tail;
	else
		tmp = l->head;
	while(tmp)
	{
		count ++;
		rc = it(tmp->curr_data);
		if(rc == CALG_ENUM_REPEAT)
			continue;
		else if(rc == CALG_ENUM_STOP)
			return count;
		if(reverse)
			tmp = tmp->prev;
		else
			tmp = tmp->next;
	}
	return count;
}
#ifdef __cplusplus
}
#endif
#endif//end of file
单元测试:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "CAlgList.h"


typedef struct {
	int a;
	int b;
}CAlgListNodeData;


#define MAX_NODE_ELEM   10000000
static CAlgListNodeData* g_NodeDataPool = NULL;
static CAlgNode* g_CAlgNodes = NULL;
static CAlgList* g_CAlgList = NULL;


extern "C" CAlgEnum TestAlgList_Enum(void* elem)
{
	CAlgListNodeData* e = (CAlgListNodeData*)elem;
	printf("%5d, a=%5d, b=%5d\n", e - g_NodeDataPool, e->a, e->b);
	return CALG_ENUM_NEXT;
}


extern "C" CAlgEnum TestAlgList_EnumNothing(void* elem)
{
	return CALG_ENUM_NEXT;
}


extern "C" static int TestAlgList_node_cmp(const void* left, const void* right, unsigned int size)
{
	CAlgListNodeData* l, *r;
	l = (CAlgListNodeData*)left;
	r = (CAlgListNodeData*)right;
	if (l->a != r->a) 
		return l->a - r->a;

	return l->b - r->b;
}


void TestAlgList_Init()
{
	g_NodeDataPool = (CAlgListNodeData*)malloc(sizeof(CAlgListNodeData)*MAX_NODE_ELEM);
	g_CAlgNodes = (CAlgNode*)malloc(sizeof(CAlgNode)*MAX_NODE_ELEM);
	g_CAlgList = (CAlgList*)malloc(sizeof(CAlgList));


	CAlgList_ReSet(g_CAlgList, sizeof(CAlgListNodeData));
}


void TestAlgList_Free()
{
	free(g_NodeDataPool);
	g_NodeDataPool = NULL;

	free(g_CAlgNodes);
	g_CAlgNodes = NULL;

	free(g_CAlgList);
	g_CAlgList = NULL;
}


void TestAlgList_AddAll_Pointer(int add_tail)
{
	CAlgNode* n = g_CAlgNodes;
	CAlgListNodeData* d = g_NodeDataPool;
	int i;
	for(i=0; i<MAX_NODE_ELEM; i++)
	{
		d->a = i+1;
		d->b = i+2;

		n[i].curr_data = (void*)d;
		if(add_tail)
			CAlgList_AddTail(g_CAlgList, &n[i]);
		else
			CAlgList_AddHead(g_CAlgList, &n[i]);

		d++;
		assert(g_CAlgList->elem_count == i +1);
	}

	i=0;
	n = g_CAlgList->head;
	do{
		if(n == g_CAlgList->head)
		{
			assert(n->prev == NULL);
		}
		if(n == g_CAlgList->tail)
		{
			assert(n->next == NULL);
		}

		d = (CAlgListNodeData*)n->curr_data;
		if(add_tail){
			assert(d->a == i+1);
			assert(d->b == i+2);
		}
		else
		{
			assert(d->a == MAX_NODE_ELEM - i);
			assert(d->b == MAX_NODE_ELEM - i +1);
		}

		i++;
	}while(n=n->next);
	assert(i == MAX_NODE_ELEM);
	assert(g_CAlgList->elem_count == MAX_NODE_ELEM);
}


void TestAlgList_RemoveHead()
{
	CAlgNode* n = g_CAlgNodes;
	CAlgListNodeData* d;
	int i;


	for(i=0; i<MAX_NODE_ELEM; i++)
	{
		n = CAlgList_RemoveHead( g_CAlgList);
		d = (CAlgListNodeData*)n->curr_data;
		assert(d->a == i+1);
		assert(d->b == i+2);
		assert(g_CAlgList->elem_count == MAX_NODE_ELEM - i -1);
	}

	assert(g_CAlgList->head == NULL);
	assert(g_CAlgList->tail == NULL);
}

void TestAlgList_RemoveTail()
{
	CAlgNode* n = g_CAlgNodes;
	CAlgListNodeData* d;
	int i;


	for(i=0; i<MAX_NODE_ELEM; i++)
	{
		n = CAlgList_RemoveTail( g_CAlgList);
		d = (CAlgListNodeData*)n->curr_data;
		assert(d->a == i+1);
		assert(d->b == i+2);
		assert(g_CAlgList->elem_count == MAX_NODE_ELEM - i - 1);
	}

	assert(g_CAlgList->head == NULL);
	assert(g_CAlgList->tail == NULL);
}


void TestAlgList_Insert_Remove()
{
	const int node_num = 10;
	CAlgNode* n = g_CAlgNodes;
	CAlgListNodeData* d = g_NodeDataPool;
	int i;
	CAlgListNodeData tmp;


	//list empty find fail
	for(i=0; i<node_num/2; i++)
	{
		d = &g_NodeDataPool[node_num/2+i];
		tmp.a = i+1;
		tmp.b = i+2;

		n = CAlgList_Find(g_CAlgList, &tmp, TestAlgList_node_cmp);
		assert(n == NULL);
	}

	//list empty remove fail
	assert (NULL == CAlgList_RemoveTail( g_CAlgList));
	assert (NULL == CAlgList_RemoveHead( g_CAlgList));
	assert (g_CAlgList->elem_count == 0);

	//add node_num/2 nodes
	for(i=0; i<node_num/2; i++)
	{
		d = &g_NodeDataPool[i];
		d->a = i+1;
		d->b = i+2;

		g_CAlgNodes[i].curr_data = (void*)d;
		CAlgList_AddTail( g_CAlgList, &g_CAlgNodes[i]);

		assert(g_CAlgList->elem_count == i +1);
	}

	assert(g_CAlgList->elem_count == node_num/2);
	printf("add 5 nodes using CAlgList_AddTail()\n");
	CAlgList_Enum(g_CAlgList,TestAlgList_Enum,0);

	//insert node_num/2 nodes into the list
	//1,      2,      3,      4,      5 
	//1,1001, 2,1002, 3,1003, 4,1004, 5,1005
	for(i=0; i<node_num/2; i++)
	{
		d = &g_NodeDataPool[node_num/2+i];
		tmp.a = i+1;
		tmp.b = i+2;

		n = CAlgList_Find( g_CAlgList, &tmp, TestAlgList_node_cmp);
		assert(n != NULL);

		d->a = 1000+i+1;
		d->b = 2000+i+1;

		g_CAlgNodes[node_num/2+i].curr_data = d;

		CAlgList_Insert(g_CAlgList, n, &g_CAlgNodes[node_num/2+i]);
	}
	printf("\nafter add 5 nodes using CAlgList_Insert()\n");
	CAlgList_Enum(g_CAlgList,TestAlgList_Enum,0);

	i=0;
	n = g_CAlgList->head;
	do{
		if(n == g_CAlgList->head)
		{
			assert(n->prev == NULL);
		}
		if(n == g_CAlgList->tail)
		{
			assert(n->next == NULL);
		}

		d = (CAlgListNodeData*)n->curr_data;
		if((i % 2) == 0)
		{
			assert(d->a == i/2+1);
			assert(d->b == i/2+2);
		}
		else
		{
			assert(d->a == 1000+i/2+1);
			assert(d->b == 2000+i/2+1);
		}

		i++;
	}while(n=n->next);
	assert(i == node_num);
	assert(g_CAlgList->elem_count == node_num);


	//remove node 1001,1002,1003,1004,1005
	//before 1,1001, 2,1002, 3,1003, 4,1004, 5,1005
	//after  1,      2,      3,      4,      5 
	for(i=0; i<node_num/2; i++)
	{
		tmp.a = 1000+i+1;
		tmp.b = 2000+i+1;
		n = CAlgList_Find( g_CAlgList, &tmp, TestAlgList_node_cmp);
		assert(n != NULL);
		assert(0 == CAlgList_RemoveNode( g_CAlgList, n));
	}
	printf("\nafter remove 5 nodes using CAlgList_RemoveNode\n");
	CAlgList_Enum(g_CAlgList,TestAlgList_Enum,0);
	assert(g_CAlgList->elem_count == node_num/2);

	i=0;
	n = g_CAlgList->head;
	do{
		if(n == g_CAlgList->head)
		{
			assert(n->prev == NULL);
		}
		if(n == g_CAlgList->tail)
		{
			assert(n->next == NULL);
		}

		d = (CAlgListNodeData*)n->curr_data;
		assert(d->a == i+1);
		assert(d->b == i+2);

		i++;
	}while(n=n->next);

	//remove head 1
	//after  2,      3,      4,      5 
	n = CAlgList_RemoveHead( g_CAlgList);
	assert(n != NULL && g_CAlgList->elem_count > 2);
	d = (CAlgListNodeData*)n->curr_data;
	assert(d->a == 1);
	assert(d->b == 2);


	//remove tail 5
	//after  2,      3,      4,      
	n = CAlgList_RemoveTail( g_CAlgList);
	assert(n != NULL && g_CAlgList->elem_count > 2);
	d = (CAlgListNodeData*)n->curr_data;
	assert(d->a == 5);
	assert(d->b == 6);

	assert(g_CAlgList->elem_count == 3);
	i=1;
	n = g_CAlgList->head;
	do{
		if(n == g_CAlgList->head)
		{
			assert(n->prev == NULL);
		}
		if(n == g_CAlgList->tail)
		{
			assert(n->next == NULL);
		}

		d = (CAlgListNodeData*)n->curr_data;
		assert(d->a == i+1);
		assert(d->b == i+2);

		i++;
	}while(n=n->next);
	assert(i == 4);
	printf("\nafter CAlgList_RemoveHead && CAlgList_RemoveTail\n");
	CAlgList_Enum(g_CAlgList,TestAlgList_Enum,0);

	//remove all
	while(CAlgList_RemoveHead( g_CAlgList))
		printf("remove...\n");

	assert(g_CAlgList->elem_count == 0);
}




#include <Windows.h>
void TestAlgList_Run()
{
	SYSTEMTIME st1, st2;
	FILETIME ft1, ft2; //100ns
	CAlgNode* n;
	int i;
	TestAlgList_Init();

	//test add head
	GetLocalTime(&st1);
	TestAlgList_AddAll_Pointer(1);
	GetLocalTime(&st2);
	SystemTimeToFileTime(&st1, &ft1);
	SystemTimeToFileTime(&st2, &ft2);
	printf("%s using %u.%03ums to add head %d nodes %02u:%02u:%02u.%03u - %02u:%02u:%02u.%03u\n", 
		__FILE__,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10000,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10, MAX_NODE_ELEM,
		st1.wHour,st1.wMinute,st1.wSecond,st1.wMilliseconds,
		st2.wHour,st2.wMinute,st2.wSecond,st2.wMilliseconds);

	//iterate all elements
	GetLocalTime(&st1);
	CAlgList_Enum(g_CAlgList,TestAlgList_EnumNothing,0);
	GetLocalTime(&st2);
	SystemTimeToFileTime(&st1, &ft1);
	SystemTimeToFileTime(&st2, &ft2);
	printf("%s using %u.%03ums to iterate %d nodes %02u:%02u:%02u.%03u - %02u:%02u:%02u.%03u\n", 
		__FILE__,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10000,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10, MAX_NODE_ELEM,
		st1.wHour,st1.wMinute,st1.wSecond,st1.wMilliseconds,
		st2.wHour,st2.wMinute,st2.wSecond,st2.wMilliseconds);

	i=0;
	GetLocalTime(&st1);
	ALGLIST_FOREACH(g_CAlgList, n);
	i++;
	ALGLIST_FOREACH_END();
	GetLocalTime(&st2);
	SystemTimeToFileTime(&st1, &ft1);
	SystemTimeToFileTime(&st2, &ft2);
	printf("%s using %u.%03ums to iterate %d nodes %02u:%02u:%02u.%03u - %02u:%02u:%02u.%03u\n", 
		__FILE__,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10000,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10, i,
		st1.wHour,st1.wMinute,st1.wSecond,st1.wMilliseconds,
		st2.wHour,st2.wMinute,st2.wSecond,st2.wMilliseconds);

	//CAlgList_Enum(CAlgList_GetAlgFunc(),g_CAlgList,TestAlgList_Enum,0);
	//remove all 
	TestAlgList_RemoveHead();

	//test add tail
	GetLocalTime(&st1);
	TestAlgList_AddAll_Pointer(0);
	GetLocalTime(&st2);
	SystemTimeToFileTime(&st1, &ft1);
	SystemTimeToFileTime(&st2, &ft2);
	printf("%s using %u.%03ums to add tail %d nodes %02u:%02u:%02u.%03u - %02u:%02u:%02u.%03u\n", 
		__FILE__,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10000,
		(ft2.dwLowDateTime-ft1.dwLowDateTime)/10, MAX_NODE_ELEM,
		st1.wHour,st1.wMinute,st1.wSecond,st1.wMilliseconds,
		st2.wHour,st2.wMinute,st2.wSecond,st2.wMilliseconds);
	//CAlgList_Enum(CAlgList_GetAlgFunc(),g_CAlgList,TestAlgList_Enum,1);
	TestAlgList_RemoveTail();

	//test find and insert
	CAlgList_ReSet(g_CAlgList, sizeof(CAlgListNodeData));
	TestAlgList_Insert_Remove();

	TestAlgList_Free();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值