链表在C语言中的实现设计

链表在C语言中的实现设计,c,data-structures,C,Data Structures,目前,我正在为C语言中的公共数据结构创建一个小型库。这主要是为了学习,但我确实计划在其他项目中使用该库,以了解它的工作情况以及问题所在。到目前为止,我对我的哈希和二叉树实现感到满意,但我不能决定链表的设计 迄今为止实现的所有数据结构都使用void指针,并且不负责创建或销毁数据,即它们只引用数据。一个设计目标是使它们尽可能通用,以提高可重用性 关于链表,我发现了三种方法: 专用列表头:列表具有专用列表头,用作抽象数据类型 仅节点:与上面的示例类似,只是所有函数都在列表_节点上运行。用于 在有效载荷

目前,我正在为C语言中的公共数据结构创建一个小型库。这主要是为了学习,但我确实计划在其他项目中使用该库,以了解它的工作情况以及问题所在。到目前为止,我对我的哈希和二叉树实现感到满意,但我不能决定链表的设计

迄今为止实现的所有数据结构都使用
void
指针,并且不负责创建或销毁数据,即它们只引用数据。一个设计目标是使它们尽可能通用,以提高可重用性

关于链表,我发现了三种方法:

  • 专用列表头:列表具有专用列表头,用作抽象数据类型

  • 仅节点:与上面的示例类似,只是所有函数都在
    列表_节点上运行
    。用于

  • 在有效载荷中:向有效载荷数据添加一个
    列表节点
    结构,并使用宏计算有效载荷的偏移量。看

  • 编辑使用宏生成类型化列表:使用宏创建列表结构和函数的特定类型版本

    1和2的示例:



  • 现在来问一个问题:这些方法中哪一种最通用?还有其他方法吗?

    请注意,您不必使用void*指针。 可以使用宏粘贴技巧为泛型类型安全数据结构生成类型/函数(通过将类型名称附加到类型和函数)


    例:

    我更喜欢第二种方法,即只使用节点

    它的优点是非常简单,因为大多数列表操作(拆分、推送、弹出、子列表等)的结果本身就是列表


    还要注意,您缺少重要的列表操作,主要是
    push()
    pop()
    。您应该利用列表允许在O(1)中插入的事实。

    对于
    索引
    大小
    等,可能最好使用
    size\u t
    ,而不是
    uint32\u t
    。您在其中有比较器,您正在尝试实现优先级队列吗?基本链表不需要比较器,而堆是处理PQUE的更好结构。您可能还需要查看sys/queue.h以了解实现情况。@tobyodavies在上述示例中,
    list\u remove
    list\u insert\u after
    需要比较器,因为这两个函数将通过将元素与数据指针指向的任何元素进行比较来找到所讨论的元素。@Dario-也许这两个函数应该使用comparator参数,而不是将其作为列表的固有部分。谢谢您的建议!示例中给出的接口并不完整,它只是为了说明这一点。实际上,我更喜欢1和2-2的混合,用于节点足够时,但1用于可以存储在lis头中的额外信息的情况(即
    结束
    大小
    ,等等)这当然是一个有趣的方法,你知道有使用sglib的项目吗?
    
    /* list.h */
    typedef struct list_t list;
    
    typedef int (*comparator)(const void* a, const void* b);
    
    list* list_new          (comparator c);
    void  list_delete       (list* l);
    void  list_insert_after (list* l, uint32_t index, void* data);
    void  list_remove       (list* l, void* data);
    uint32_t list_size      (list* l);
    /* other functions operating on lists */
    
    /* list.c */
    #include "list.h"
    
    typedef struct list_node_t {
      struct list_node_t* next;
      struct list_node_t* prev;
      void* data;
    } list_node;
    
    struct list_t {
      list_node* begin;
      list_node* end;
      uint32_t   size;
      comparator cmp;
    }