我目前正在关注Steve Yegge关于准备技术编程面试的建议:http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html
在他关于图表的部分中,他说:
有三种基本方法 表示内存中的图形(对象 和指针,矩阵和邻接 列表),你应该熟悉 你自己与每个表示和 它的优点和缺点。
矩阵和邻接列表表示的优缺点在CLRS中描述,但我无法找到将这些与对象表示进行比较的资源。
只要想一想,我就可以自己推断一些,但我想确保我没有错过一些重要的东西。如果有人能够全面地描述这一点,或者指向我这样做的资源,我将非常感激。
答案 0 :(得分:89)
对象和指针
这些只是像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以更具伸缩性的方式处理它们。
哦和BTW,here是这篇文章的精彩摘要,带有精美的图片;)
答案 1 :(得分:7)
对象和指针与邻接列表大致相同,至少是为了比较使用这些表示的算法。
比较
struct Node {
Node *neighbours[];
};
与
struct Node {
Node *left;
Node *right;
};
如果比使用命名指针更容易使用,则可以在后一种情况下轻松构建邻居列表。
答案 2 :(得分:4)
对象表示(incidence list)的优点是两个相邻的顶点共享边的相同实例。这使得使用无向边数据(长度,成本,流量或甚至方向)进行操作变得容易。但是它为指针使用了额外的内存。