C语言通用双向链表的实现

作者:朱克锋

 转载请注明出处: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;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值