【问题标题】:Design of a linked list implementation in CC语言中链表实现的设计
【发布时间】:2011-06-22 08:27:52
【问题描述】:

目前我正在为 C 中的常见数据结构创建一个小型库。这主要是为了学习目的,但我确实计划在其他项目中使用这个库,看看它的工作情况以及问题出在哪里.到目前为止,我对哈希和二叉树的实现很满意,但我无法决定链表的设计。

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

关于链表,到目前为止,我发现了三种方法:

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

  2. 仅限节点:与上面的示例类似,但所有函数都在 list_node 上运行。用于GLib

  3. 在有效载荷中:在有效载荷数据中添加list_node 结构,并使用宏计算有效载荷的偏移量。见lists in the linux kernel

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

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


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

【问题讨论】:

  • 最好将size_t 用于indexsize 等,而不是uint32_t
  • 你有比较器,你想实现一个优先级队列吗?基本链表不需要比较器,堆是处理 pqueue 的更好结构
  • 你可能也想看看 sys/queue.h 的实现。
  • @tobyodavies 在上面的示例中,list_removelist_insert_after 需要比较器,因为这两个函数会通过将其与数据指针指向的任何内容进行比较来找到有问题的元素.
  • @Dario - 也许这两个函数应该采用比较器参数,而不是使其成为列表的固有部分。

标签: c data-structures


【解决方案1】:

我更喜欢第二种方法,即仅节点。

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

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

【讨论】:

  • 感谢您的建议!示例中给出的界面并不完整,只是为了说明问题。
  • 实际上,当节点足够时,我更喜欢 1 和 2 - 2 的混合,但在可以存储在 lis 头中的额外信息的情况下,我更喜欢 1(即end,@ 987654324@ 等)可以显着提高速度。
【解决方案2】:

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

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

【讨论】:

  • 当然是一个有趣的方法,你知道使用 sglib 的任何项目吗?
猜你喜欢
  • 2021-05-20
  • 2015-06-30
  • 1970-01-01
  • 2014-05-07
  • 2012-06-07
  • 2011-05-09
  • 2013-11-25
  • 2014-08-20
  • 1970-01-01
相关资源
最近更新 更多