简体   繁体   English

在C中设计链表实现

[英]Design of a linked list implementation in C

At the moment I am working on creating a small library for common data structures in C. This is mainly for learning purposes, but I do plan to use this library in other projects to see how well it works and where the problems are. 目前我正在为C中的公共数据结构创建一个小型库。这主要用于学习目的,但我计划在其他项目中使用此库来查看它的工作原理以及问题所在。 So far I'm content with my hash and binary tree implementation, but I cannot decide on the design of the linked list. 到目前为止,我对我的哈希和二叉树实现感到满意,但我无法决定链表的设计。

All the data structures implemented so far work with void pointers and take no responsibility for creating or destroying data, ie they only reference the data. 到目前为止实现的所有数据结构都使用void指针,并且不负责创建或销毁数据,即它们仅引用数据。 One design goal is to keep them as generic as possible to increase the reuseability. 一个设计目标是使它们尽可能通用,以提高可重用性。

Regarding the linked list, I've found three approaches so far: 关于链表,到目前为止我找到了三种方法:

  1. Dedicated list head : the list features a dedicated list head which is used as an abstract data type. 专用列表头 :列表具有专用列表头,用作抽象数据类型。

  2. Nodes only : like the example above, except that all functions operate on a list_node . 仅限节点 :与上面的示例类似,只是所有函数都在list_nodelist_node Used in GLib . 用于GLib

  3. In payload : add a list_node structure to the payload data and calculate the offset to the payload with a macro. 在有效负载中 :将list_node结构添加到有效负载数据,并使用宏计算有效负载的偏移量。 See lists in the linux kernel 请参阅linux内核中的列表

  4. EDIT Generate typed lists with macros : use macros to create type-specific versions of the list structures and functions. 编辑使用宏生成类型化列表 :使用宏来创建列表结构和函数的特定于类型的版本。

    Example for 1 and 2: 1和2的示例:


/* 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;
}


Now to the question: which of these approaches is the most versatile? 现在回答这个问题:哪种方法最通用? Are there any other approaches? 还有其他方法吗?

I prefer the second approach, ie nodes only. 我更喜欢第二种方法,即仅节点。

It has the advantage of being extremely simple, since the results of most list operations (split, push, pop, sublist, ...) are themselves lists. 它具有极其简单的优点,因为大多数列表操作(拆分,推送,弹出,子列表......)的结果本身就是列表。

Also note that you're lacking important list operations, mainly push() and pop() . 另请注意,您缺少重要的列表操作,主要是push()pop() You should make use of the fact that lists allow insertion in O(1). 您应该利用列表允许插入O(1)的事实。

Note that you don't necessarily have to use void * pointers. 请注意,您不一定要使用void *指针。 You can use macro pasting tricks to generate types/function(by appending type name to types and functions) for generic type safe data structures. 您可以使用宏粘贴技巧为通用类型安全数据结构生成类型/函数(通过将类型名称附加到类型和函数)。

ex.: http://sglib.sourceforge.net/ 例如: http//sglib.sourceforge.net/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM