链表在图的邻接表示中的优势

Advantages of linked lists in adjacency representation of a graph

Skiena 的 Algorithm Design Manual(第 3 版,第 204 页)引用 邻接列表 而不是一般的邻接表示,定义它们为每个顶点 a 分配一个单链表 L_a 和底层集合 set(L_a) = {b | (x, b) <- edges, x == a}.

令我惊讶的是,Skiena 将单向链表作为实现集合的最终数据结构呈现 L_a。我的印象是,与数组和散列table相比,链表普遍失宠,因为:

其他来源以不同方式处理邻接表。例如 Wikipedia 提供了一个实现,其中 L_a 是数组。在 Stone 的 函数式编程算法 中,L_a 是无序集合,最终实现为 Scheme 列表(反过来让我觉得很奇怪)。

My Question: Is there a consideration I'm missing which gives singly linked lists a significant advantage in adjacency representations?

我郑重请求,在您投票关闭此问题之前,或 post 以不加理会的语气评论 table 之前,您问问自己是否真的在帮助该网站实现其目标通过这样做。

我认为在大多数现实世界的用例中,单链表作为邻接表的默认表示形式没有任何普遍共识。

但是,单链表几乎是您可能拥有的最限制邻接表的实现,因此在一本关于“算法设计”的书中,它使得在这种表示中考虑邻接列表是有意义的,除非你需要从它们中得到一些特殊的东西,比如随机访问、双向迭代、二进制搜索等。

当谈到算法在显式图上的实际实现时(大多数实现是在隐式图上),我认为单链表通常不是一个好的选择。

我的首选邻接表图形表示是一对平行数组:

  1. 顶点编号从 0 到 n-1
  2. 有一个 边数组,其中包含按源顶点编号排序的所有边。对于无向图,每条边在这里出现两次。源顶点通常不需要存储在这里。
  3. 有一个顶点数组,它为每个顶点存储其边在边数组中的结束位置。

这是一个很好的、紧凑的、缓存友好的表示,易于使用并且只需要两次分配。

我通常可以找到一种简单的方法来在线性时间内构建这样的图,首先用计数填充顶点数组,然后将计数更改为起始位置(移位累积和),然后填充边数组,随着边缘的添加推进这些位置。