比较对象图表示与邻接表和矩阵表示


81

我目前正在按照史蒂夫·叶格(Steve Yegge)的建议来准备进行技术编程采访:http : //steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html

他在图部分中指出:

有三种基本方法可以在内存中表示图形(对象和指针,矩阵和邻接表),并且您应该熟悉每种表示形式及其优缺点。

矩阵和邻接列表表示的优缺点在CLRS中进行了描述,但是我一直找不到能够将这些与对象表示进行比较的资源。

只是考虑一下,我自己就可以推断出其中的一些内容,但是我想确保自己没有错过任何重要的事情。如果有人可以对此进行全面描述,或者指向我提供这样做的资源,我将不胜感激。


归纳图如何-这些归为三类?
埃里克·卡普伦

Answers:


94

对象和指针

这些只是基本数据结构,就像另一个答案中的hammar所说的那样,Java您可以用诸如边和顶点之类的类来表示。例如,一条边连接两个顶点,可以是有向的也可以是无向的,并且可以包含权重。顶点可以具有ID,名称等。大多数情况下,它们两个都具有其他属性。因此,您可以像这样构建图形

Vertex a = new Vertex(1);
Vertex b = new Vertex(2);
Edge edge = new Edge(a,b, 30); // init an edge between ab and be with weight 30  

这种方法通常用于面向对象的实现,因为它对于面向对象的用户更具可读性和便利性。

矩阵

矩阵只是一个简单的二维数组。假设您有一个顶点ID,可以将其表示为一个int数组,如下所示:

int[][] adjacencyMatrix = new int[SIZE][SIZE]; // SIZE is the number of vertices in our graph
adjacencyMatrix[0][1] = 30; // sets the weight of a vertex 0 that is adjacent to vertex 1

这通常用于需要索引访问的密集图。您可以以此表示一个非/有向的加权结构。

邻接表

这只是简单的数据结构组合,我通常使用来实现HashMap<Vertex, List<Vertex>>HashMultimap番石榴中可以使用类似的东西。

这种方法很酷,因为您有O(1)个(经摊销的)顶点查找,它向我返回了我需要的该特定顶点的所有相邻顶点的列表。

ArrayList<Vertex> list = new ArrayList<>();
list.add(new Vertex(2));
list.add(new Vertex(3));
map.put(new Vertex(1), list); // vertex 1 is adjacent to 2 and 3

这用于表示稀疏图,如果您要向Google申请,则应该知道该网络图是稀疏的。您可以使用BigTable以更可扩展的方式处理它们。

哦,顺便说一句,是带有精美图片的这篇帖子的很好总结;)


这种方法很酷,因为您具有O(1)顶点查找,所以这种复杂性略有错误,特别是O(1 + alpha),其中alpha =哈希映射中的槽数/顶点数。因此,我建议使用数组而不是哈希映射
Timofey 2013年

@Tim将O(1)摊销。您的复杂度计算是实现的重要依据。请参阅HashMapdocs.oracle.com/javase/7/docs/api/java/util/HashMap.html)的javadoc,其中指出:This implementation provides constant-time performance for the basic operations= O(1)摊销。
Thomas Jungblut

6
@Tim我想这里的每个人都知道数组访问比任何HashTable用法都快。因此,无需花费很小的恒定Alpha开销就可以忽略不计。
Thomas Jungblut13年

2
请不要误会我的意思,我不会冒犯您一个很好的答案,但是我有一种感觉,您的答案可能会有所改善,所以为什么不在这里提它:)
Timofey

2
@Tim我将摊销后的注释添加到了答案中。谢谢。
Thomas Jungblut 2013年

7

对象和指针与邻接表大部分相同,至少出于比较使用这些表示形式的算法的目的。

相比

struct Node {
    Node *neighbours[];
};

struct Node {
    Node *left;
    Node *right;
};

如果后一种情况比命名指针更容易使用,则可以在后一种情况下轻松地即时构造邻居列表。



1

另一个很好的资源:可汗学院-“表示图”

除了邻接表和邻接矩阵之外,它们还将“边列表”列出为图形表示的第三种类型。边缘列表可以解释为类似于Thomas的“对象和指针”答案中的“边缘对象”的列表。

优势:我们可以存储有关边缘的更多信息(由Michal提及)

缺点:它的数据结构非常慢:

  • 查找边:O(log e)
  • 移除边缘:O(e)
  • 查找与给定节点相邻的所有节点:O(e)
  • 确定两个节点之间是否存在路径:O(e ^ 2)

e =边数

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.