添加边缘到未加权的有向图效率?

时间:2017-03-22 22:37:09

标签: python algorithm data-structures

我有三个图表表示为python词典

A: {1:[2], 2:[1,3], 3:[]}. 

B: {1: {neighbours:[2]}, 2: {neighbours:[1,3]}, 3: {neighbours:[]}}

C: {1: {2:None}, 2: {1:None, 3:None}, 3: {}}

我有一个hasEdge和addEdge函数

def addEdge(self, source, target):

assert self.hasNode(source) and self.hasNode(target)
if not self.hasEdge(source, target):
    self.graph[source][target] = None

def hasEdge(self, source, target):

    assert self.hasNode(source) and self.hasNode(target)
    return target in self.graph[source]

我不确定哪种结构对每个函数最有效,我的直接想法是第一个是最有效的添加边缘,如果它有边缘,C将是最有效的返回

2 个答案:

答案 0 :(得分:1)

对我来说,C似乎是最有效的,因为你正在进行平均O(1)的查找。 (请注意这是一般情况,不是最糟糕的情况。)使用邻接列表,您的情况最差线性搜索。

对于稀疏图,您可能希望使用邻接列表(A),因为它们占用的空间更少。但是,对于密集图,选项C应该是最有效的。

A和B将具有非常相似的运行时 - 渐近相同。除非您希望添加到这些节点的邻居之外的数据,否则我会选择A.

我不熟悉python;但是,对于Java,可以通过使用HashSet(set)来改进选项C,这将减少您的空间需求。运行时与使用HashMap相同,但是set不存储值 - 只有键,这是你想要检查两个节点之间是否存在边缘的那些。

所以,澄清一下:

对于运行时,选择C.您将获得平均情况O(1)边缘添加。要改进C以减少内存消耗,请使用集合而不是映射,因此您不必为值分配空间。

对于内存,如果您有稀疏图,请选择A.您将节省大量内存,并且在运行时方面不会损失太多。作为参考,稀疏是指节点没有太多邻居;例如,当每个节点在具有20个节点的图中具有大约2个邻居时。

答案 1 :(得分:1)

BC是经典的邻接列表。 O(1)是一个邻接列表,但对列表使用O(N)结构而不是D结构。但实际上,你应该使用邻接集set.contains(s)

在Python中O(1)是一个graph = { 1: set([2]), 2: set([1, 3], 3: set() } 操作。

所以我们可以做到

addEdge(from, to)

然后我们的graph[from].add(to) graph[to].add(from)

hasEdge(from,to)

我们的to in graph[from] 只是

{{1}}