作者:朱克锋
转载请注明出处:http://blog.csdn.net/linux_zkf/article/details/7493159
专用链表在这里是指该链表的实现和调用耦合在一起,只能被一个调用者使用,而不能单独在其他地方被重用。通用链表则相反,它具有通用性,可以在多处被重复使用。尽管通用链表相对专用链表来说有很多优越之处,不过草率地断定通用链表比专用链表好也是不公正的,因为它们都有自己的优点和适用范围。
专用链表的优点
性能更高。专用链表的实现和调用在一起,可以直接访问数据成员,省去了包装函数带来的性能开销,可以提高时间性能。专用链表无需实现完整的接口,只要满足自己的需要就行了,生成的代码更小,因此可以提高空间性能。
依赖更少。自己实现不用依赖于别人。有时候你要写一个规模不大的跨平台程序,比如想在展讯手机平台和MTK手机平台上运行,虽然有现存的库可用,但你又不想把整个库移植过去,那么实现一个专用链表是不错的选择。
实现简单。实现专用链表时,不需要考虑在各种复杂应用情况下的特殊要求,也不需要提供完整的接口,所以实现起来比通用链表更为简单。
通用链表的优点(从全局来看)
可靠性更高。通用链表的实现要复杂得多,复杂的东西意味着不可靠。但它是可以重复使用的,其存在的问题会随每一次重用而被发现和改正,慢慢地就形成一个可靠的函数库。
开发效率更高。通用链表的实现要复杂得多,复杂的东西也意味着更高的开发成本。同样因为它是可以重复使用的,开发成本会随每一次重用而降低,从整个项目来看,会大大提高开发效率。
注:这段话摘自《系统程序员成长计划》
接下来是对通用链表实现的说明:
先建立通用链表的存储结构:
typedef struct _DListNode
{
void *data;
struct _DListNode *prev;
struct _DListNode *next;
}DListNode;
typedef struct _DList
{
DListNode *head;
DListNode *current;
}DList;
接下来定义一个enum来存放程序中函数的返回值,可以不定义
typedef enum _Ret
{
RET_OK = 1,
RET_FAULT,
RET_OOM,
}Ret;
为了使程序更具通用性可以定义一个回调函数原型,用于回调
typedef void*(*VisitFunc)(void *ctx, void* data);
typedef void (*DesFunc)(DList *dlist, int index);
定义一个用于测试的宏
#define return_val_if_fail(p, val)/
if(!(p)){printf("%s:%d"#p" failed./n",__func__,__LINE__); return val;}
下面定义通用双向链表的基本操作,包括:
DList *dlist_create();
int dlist_len(DList *dlist);
DListNode *dlist_get(DList *dlist, int index);
Ret dlist_delete(DList *dlist, int index);
Ret dlist_add(DList *dlist, int index, void *data);
//void dlist_print(DList *dlist, void( *print_func)(void* data));
void *dlist_foreach(DList *dlist, VisitFunc visit_func, void *ctx);
Ret dlist_destroy(DList *dlist,DesFunc des_func, int index);
头文件基本定义结束,保存为dlist.h
为了优化一般会在头文件中定义选择编译的宏
#ifndef DLIST_H
#define DLIST_H
。。。
。。。
#endif /*DLIST_H*/
避免重复编译
完整头文件如下(dlist.h):
#ifndef DLIST_H
#define DLIST_H
/*
* File: dlist.h:通用双向链表函数实现
*/
typedef struct _DListNode
{
void *data;
struct _DListNode *prev;
struct _DListNode *next;
}DListNode;
typedef struct _DList
{
DListNode *head;
DListNode *current;
}DList;
typedef enum _Ret
{
RET_OK = 1,
RET_FAULT,
RET_OOM,
}Ret;
typedef void*(*VisitFunc)(void *ctx, void* data);
typedef void (*DesFunc)(DList *dlist, int index);
DList *dlist_create();
int dlist_len(DList *dlist);
DListNode *dlist_get(DList *dlist, int index);
Ret dlist_delete(DList *dlist, int index);
Ret dlist_add(DList *dlist, int index, void *data);
//void dlist_print(DList *dlist, void( *print_func)(void* data));
void *dlist_foreach(DList *dlist, VisitFunc visit_func, void *ctx);
Ret dlist_destroy(DList *dlist,DesFunc des_func, int index);
#define return_val_if_fail(p, val) /
if(!(p)) {printf("%s:%d"#p" failed./n", __func__, __LINE__); return val;}
#endif/*DLIST_H*
以下是函数实现部分(dlist.c):
#include "dlist.h"
#include <malloc.h>
/*
* File: dlist.c:通用双向链表函数实现
*/
/*
*功能:实现一个DList结构体的初始化
*参数:void
*返回:DList结构体
*/
//..........create head..............
DList *dlist_create()
{
DList *dlist = (DList *)calloc(1, sizeof(DList));
if(dlist == NULL)
{
return NULL;
}
dlist->head = (DListNode *)calloc(1, sizeof(DListNode));
if(dlist->head == NULL)
{
free(dlist);
dlist = NULL;
return NULL;
}
dlist->current = dlist->head;
return dlist;
}
/*
*分配内存
*/
//........malloc node..................
static DListNode *dlist_alloc()
{
return (DListNode *)calloc(1, sizeof(DListNode));
}
/*
*检查输入的数据
*/
//............ data check.........
int data_dlist_check(DList *dlist, void *data)
{
int flag = 1;
// No head
if(dlist == NULL)
{
return flag = 0;
}
// Incorrect data
if(data == NULL)
{
return flag = 0;
}
return flag;
}
/*
*功能:添加元素
*参数:dlist:指定链表 index: 添加的位置 data:加入的数据的指针
*返回:Ret
*/
Ret dlist_add(DList *dlist, int index, void *data)
{
int flag = 1;
int len = 0;
DListNode *node = NULL;
DListNode *dlistnode = NULL;
//
return_val_if_fail(dlist != NULL&&data != NULL, RET_FAULT);
flag = data_dlist_check(dlist, data);
if(flag == 0)
{
return RET_FAULT;
}
len = dlist_len(dlist);
//
return_val_if_fail(index <= len, RET_FAULT);
if(index > len )
{
return RET_FAULT;
}
node = dlist_alloc();
if(node == NULL)
{
return RET_OOM;
}
node->data =data;
// node->data = strcpy(data);
if( (len == 0 &&index == 0)|| index < 0)
{
//tail
dlist->current->next = node;
node->prev = dlist->current;
dlist->current = node;
return RET_OK;
}
else if(len != 0&& index == 0)
{
//head
dlist->head->next->prev = node;
node->prev = dlist->head;
node->next = dlist->head->next;
dlist->head->next = node;
return RET_OK;
}
else if(len != 0&& index !=0)
{
dlistnode = dlist_get(dlist, index);
if(dlistnode == NULL)
{
return RET_FAULT;
}
dlistnode->prev->next = node;
node->prev = dlistnode->prev;
node->next = dlistnode;
dlistnode->prev = node;
return RET_OK;
}
return RET_FAULT;
}
/*
*功能:删除指定位置的值
*参数:参数:dlist:指定链表 index:位置
*/
//.........del.............
Ret dlist_delete(DList *dlist, int index)
{
int len = 0;
DListNode *dlistnode = NULL;
//
return_val_if_fail(dlist != NULL, RET_FAULT);
if(dlist == NULL)
{
return RET_FAULT;
}
len = dlist_len(dlist);
//
return_val_if_fail(index <= len, RET_FAULT);
if(index > len )
{
return RET_FAULT;
}
if(index > 0&&index <len)
{
dlistnode = dlist_get(dlist, index);
if(dlistnode == NULL)
{
return RET_FAULT;
}
dlistnode->next->prev = dlistnode->prev;
dlistnode->prev->next = dlistnode->next;
dlistnode->prev = NULL;
dlistnode->next = NULL;
dlistnode->data = NULL;
free(dlistnode);
dlistnode = NULL;
return RET_OK;
}
else if(index <= 0 || index == len)
{
dlistnode = dlist->current->prev;
dlist->current->prev->next = NULL;
dlist->current->prev = NULL;
dlist->current->data = NULL;
free(dlist->current);
dlist->current = dlistnode;
return RET_OK;
}
return RET_FAULT;
}
/*
*功能:得到节点
*参数:dlist:要操作的链表指针地址 index:位置
*/
//..........get node.......
DListNode *dlist_get(DList *dlist, int index)
{
return_val_if_fail(dlist != NULL, NULL);
int n = 1;
DListNode *dlistnode = NULL;
dlistnode = dlist->head;
while (n <= index)
{
dlistnode = dlistnode->next;
n = n + 1;
}
return dlistnode;
}
/*
*功能:遍历
*参数:dlist:指定链表 visitfunc:回调函数 ctx:上下文
*返回:Ret
*/
void *dlist_foreach(DList *dlist, VisitFunc visit_func,void *ctx)
{
return_val_if_fail(dlist != NULL&&visit_func !=NULL, NULL);
DListNode *ipointer = NULL;
void *retp = NULL;
ipointer = dlist->head->next;
for (ipointer ; ipointer != NULL; )
{
retp = visit_func(ctx, ipointer->data);
ipointer = ipointer->next;
}
return retp;
}
/*
*功能:长度
*参数:dlist:指定链表
*返回:大小
*/
int dlist_len(DList *dlist)
{
return_val_if_fail(dlist != NULL, RET_FAULT);
int len = 0;
DListNode *dlistnode = NULL;
dlistnode = dlist->head;
while (dlistnode->next != NULL)
{
dlistnode = dlistnode->next;
len = len + 1;
}
return len;
}
/*
*功能:释放指定链表内存
*参数:dlist:指定链表
*返回:Ret
*/
//..........free list .............
Ret dlist_destroy(DList *dlist, DesFunc des_func, int index)
{
DListNode* cursor = NULL;
if(des_func != NULL)
{
des_func(dlist, index);
}
else
{
while (dlist->current != NULL && dlist->current != dlist->head)
{
cursor = dlist->current->prev;
free(dlist->current);
dlist->current = cursor ;
}
if(dlist->head != NULL)
{
free(dlist->head);
dlist->head = NULL;
dlist->current = NULL;
}
if(dlist != NULL)
{
free(dlist);
dlist = NULL;
}
}
return RET_OK;
}