我正在尝试为DAG实现拓扑排序算法。 (http://en.wikipedia.org/wiki/Topological_sorting) 这个简单算法的第一步是找到零度数的节点,如果没有二次算法,我找不到任何方法。
我的图形实现是一个简单的邻接列表,基本过程是循环遍历每个节点,每个节点都经过每个邻接列表,因此复杂度为O(|V| * |V|)
。
拓扑排序的复杂性是O(|V| + |E|)
所以我认为必须有一种方法以线性方式计算所有节点的度数。
答案 0 :(得分:2)
您可以在从图中删除节点的同时维护所有顶点的indegree,并维护零indegree节点的链接列表:
indeg[x] = indegree of node x (compute this by going through the adjacency lists)
zero = [ x in nodes | indeg[x] = 0 ]
result = []
while zero != []:
x = zero.pop()
result.push(x)
for y in adj(x):
indeg[y]--
if indeg[y] = 0:
zero.push(y)
那就是说,使用DFS的拓扑排序在概念上要简单得多,恕我直言:
result = []
visited = {}
dfs(x):
if x in visited: return
visited.insert(x)
for y in adj(x):
dfs(y)
result.push(x)
for x in V: dfs(x)
reverse(result)
答案 1 :(得分:0)
您可以在o(|v|+|e|)
中实现它。按照以下步骤进行操作:
inDegree
,outDegree
,用于维护每个节点的进出边缘的计数,并将其初始化为0. edge (u,v)
,增加u的outdegree
计数,并为v增加indegree
的计数。o(v +e)
中的邻接列表,并且o(|v|+|e|)
中的每个u都会具有indegree和outdegree。 答案 2 :(得分:0)
您提到的访问邻接节点的复杂性不太正确( O(n 2 )),因为如果您仔细考虑,您会注意到这是更像是BFS搜索。因此,您只访问每个节点和每个边缘一次。因此,复杂度为 O(m + n)。其中, n 是节点数, m 是边数。
答案 3 :(得分:-1)
您还可以使用DFS进行拓扑排序。在处理每个节点后,您不需要额外的传递来计算in-degree。