我有三个图表表示为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将是最有效的返回
答案 0 :(得分:1)
对于稀疏图,您可能希望使用邻接列表(A),因为它们占用的空间更少。但是,对于密集图,选项C应该是最有效的。
A和B将具有非常相似的运行时 - 渐近相同。除非您希望添加到这些节点的邻居之外的数据,否则我会选择A.
我不熟悉python;但是,对于Java,可以通过使用HashSet(set)来改进选项C,这将减少您的空间需求。运行时与使用HashMap相同,但是set不存储值 - 只有键,这是你想要检查两个节点之间是否存在边缘的那些。
所以,澄清一下:
对于运行时,选择C.您将获得平均情况O(1)边缘添加。要改进C以减少内存消耗,请使用集合而不是映射,因此您不必为值分配空间。
对于内存,如果您有稀疏图,请选择A.您将节省大量内存,并且在运行时方面不会损失太多。作为参考,稀疏是指节点没有太多邻居;例如,当每个节点在具有20个节点的图中具有大约2个邻居时。
答案 1 :(得分:1)
B
和C
是经典的邻接列表。 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}}