【发布时间】:2011-06-22 08:27:52
【问题描述】:
目前我正在为 C 中的常见数据结构创建一个小型库。这主要是为了学习目的,但我确实计划在其他项目中使用这个库,看看它的工作情况以及问题出在哪里.到目前为止,我对哈希和二叉树的实现很满意,但我无法决定链表的设计。
目前实现的所有数据结构都使用void 指针,并且不负责创建或销毁数据,即它们只引用数据。一个设计目标是使它们尽可能通用,以提高可重用性。
关于链表,到目前为止,我发现了三种方法:
专用列表头:列表具有专用列表头,用作抽象数据类型。
仅限节点:与上面的示例类似,但所有函数都在
list_node上运行。用于GLib。在有效载荷中:在有效载荷数据中添加
list_node结构,并使用宏计算有效载荷的偏移量。见lists in the linux kernel-
编辑 使用宏生成类型列表:使用宏来创建列表结构和函数的特定类型版本。
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用于index、size等,而不是uint32_t。 -
你有比较器,你想实现一个优先级队列吗?基本链表不需要比较器,堆是处理 pqueue 的更好结构
-
你可能也想看看 sys/queue.h 的实现。
-
@tobyodavies 在上面的示例中,
list_remove和list_insert_after需要比较器,因为这两个函数会通过将其与数据指针指向的任何内容进行比较来找到有问题的元素. -
@Dario - 也许这两个函数应该采用比较器参数,而不是使其成为列表的固有部分。
标签: c data-structures