【问题标题】:Graph incidence list implementation图关联列表实现
【发布时间】:2010-10-11 07:05:42
【问题描述】:
我正在考虑图形数据结构的实现,并且正在研究“发病率列表”表示。这里有一个简单的描述:
Incidence list
所以图中的每个顶点都存储了一个它所发生的边的列表。
鉴于我的图是有向图,从这个描述中我不太清楚几点:
- 图本身是否也存储所有边的列表?
- 顶点只存储传出边,还是传入和传出?
- 如果两者都有,它们是否在单独的列表中?
我对其他图表示(邻接表、邻接矩阵、边表、关联矩阵)非常熟悉,所以这不是关于图实现的一般问题,只是这个特定的问题。
任何指针将不胜感激。
【问题讨论】:
标签:
java
graph
directed-graph
【解决方案1】:
我知道我可能提出了一个老生常谈的问题,但我觉得发表评论是合适的。
您可以制作关联列表图结构,也可以针对有向图对其进行调整。
考虑一个LinkedList<Vertex> 对象和一个LinkedList<Edge> 对象。这将允许您遍历所有边和所有顶点,但不包含有关所有内容如何连接的信息。
假设我们添加了几个LinkedList<Connection> 对象。实际上,每个Vertex 一个。 Connection 就是 Edge 和 Vertex 相遇的地方。因此,Edge 将有两个 Connection 对象(对于无向图),Vertex 将有一个 LinkedList<Connection> 对象,表示与连接到它的每个 Edge 的连接。这实质上是一个发病率列表。
如果您删除其中一些 Connection 对象,您可以修改它以表示有向图。更具体地说,您必须选择没有这些引用的位置。如果您不想看到Vertex 中的Edge,您可以选择从关联的LinkedList<Connection> 中删除Connection(对于上面的示例,N2 将有一个空的LinkedList<Connection>) .相反,您可以选择在 Edge 上将引用设为可选(对于上面的示例,E1 将有一个 Connection 指向 N2 和一个 Connection null,允许从 E1 遍历到 N2,但不能返回到 N1。您选择如何实现这将完全取决于您。一个更直观 - 边缘是定向的,因此删除边缘上的连接以指示它们走哪条路似乎是合乎逻辑的。另一个起初可能看起来有点复杂,但是将阻止您在进行广度优先和深度优先搜索时不必要地跳到无处可去的边缘。
点形式:
在我的发生率列表的实现中,我有。您的实施需要这样做吗?
严格来说,您可以通过仅存储传出边来获得。然而,回溯算法可能会受益于能够沿着他们经过的参考进行回溯。当然,您可以通过某种历史记录来实现这一点,因此可能不需要考虑太多。
如果你两者都做,你可能需要一些方法来区分它是传入还是传出。无论是通过在顶点上拥有两个LinkedList<Connection> 对象,还是通过在Connection 上拥有一个boolean pointingToVertex 原语,或其他方式。也许您的Edge 将是有向的,而无向边将由指向相反方向的两条条边组成。根据您的结构的需要进行考虑。
【解决方案2】:
我通过以下方式实现了一个关联列表,没有发现无向图有任何问题。我也实现了几种图拓扑算法。
HashMap<VertexT, HashSet<EdgeT>> incidenceMap;
使用集合的映射保证顶点查找的 O(1) 和边插入和删除的摊销 O(1) 复杂度。保留边的关联列表而不是相邻的顶点列表只是携带边本身的某些特定信息的一种方式。这对于抽象算法也很有用,例如,当您将权重与边缘相关联时。
编辑:
我已经更新了维基百科上的talks“发病率列表”主题。
【解决方案3】:
经过进一步研究和思考,我得出的结论是不存在发生率列表图数据结构。
我认为维基百科的文章是作者头脑中一些混乱的产物。
感谢所有阅读此问题并花时间研究此问题的人。
阿尔芒