我正在尝试在C中实现单链表。您看到在互联网上浮动的常见实现类似于
typedef struct {
int head;
Node *tail;
} Node;
使用
等方法Node cons(int head, Node tail) {
Node y;
y.head = head;
y.tail = malloc(sizeof(Node));
*y.tail = tail;
}
表现非常重要。有没有办法在C中实现比这更快的链表?例如,摆脱内存分配(y.tail = malloc(sizeof(Node))
)应该会显着提高速度。
答案 0 :(得分:18)
是的,有...这被称为内存池。类似于线程池。基本上,您在Node类型的程序开头分配一个内存区域。指向此区域的指针存储在数组中。在你的cons函数中,你所做的只是从数组中获取指针。这并没有提高整体速度,但是如果你经常进行内存分配,这会增加程序的响应速度,而代价是数组的某些空间
答案 1 :(得分:11)
非常快地附加到链接列表? rope(不限于经过少量修改的字符串)将允许您批量分配内存(提高性能),同时不会惩罚附加到列表末尾的内容。
答案 2 :(得分:5)
什么操作应该快:插入,检索,所有?总是需要权衡。您的解决方案是否需要可扩展?链接列表不是。
如果您希望/需要坚持链接列表,您可以将其存储到结构数组中,该结构数组具有指示链接列表中下一个条目的索引的字段。插入将非常快,没有任何分配,缺点是您必须事先知道元素的数量 - 或者在表格满了时重新分配表格。
请参阅the Wikipedia page on linked list的“使用节点数组的链接列表”小节。
答案 3 :(得分:3)
我认为您的代码中存在一些混淆。在它的核心链接列表是:
typdef struct _node {
...
struct _node *next;
} NODE;
大多数实现都会有一个void *
来挂起有效负载。现在这不是特别重要。
列表插入必须连接指针。对于简单地添加节点(并忽略添加有效载荷),如果节点位于列表的头部或尾部,则进行1次分配;如果节点位于中间,则进行2次分配。没有太多办法可以解决这个问题。
有时,简单列表仅使用节点结构,因此尾部插入需要遍历。这很昂贵。拥有一个具有第一个和最后一个节点知识的特殊头部结构可以消除这种成本。
通过将其作为跳过列表(http://en.wikipedia.org/wiki/Skip_list)实现,可以加快遍历速度。虽然在节点插入期间需要注意优化(并且在插入期间会获得更多指针分配)。
答案 4 :(得分:2)
如果您关注malloc碎片,您可以请求大量多个大小的Node,并在每次复制Node值时按sizeof(Node)继续递增指针。
答案 5 :(得分:2)
我建议你使用linux内核列表实现:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=include/linux/list.h
(无额外内存分配)
答案 6 :(得分:0)
检查这个单链表实现的速度:
http://web.archive.org/web/20071103112712/http://stsdas.stsci.edu/bps/linked_list.html
答案 7 :(得分:0)
如果您需要的唯一操作是推送,弹出和迭代,那么您可以将元素放入数组中而不是链接列表。推送和弹出元素只是修改一个数字(第一个或最后一个元素的索引)。阵列的正面和背面可以循环连接,因此可以自由推动元件,而不会出现阵列结束的问题。