最有效的方式来按顺序访问DAG的节点

时间:2010-08-26 09:27:41

标签: algorithm performance language-agnostic graph

我有一个大的(100,000多个节点)定向非循环图(DAG),并且希望按顺序在每个节点上运行“访问者”类型函数,其中顺序由图中的箭头定义。即节点的所有父节点都保证在节点本身之前被访问。

如果两个节点没有直接或间接地相互引用,那么我不关心它们被访问的顺序。

最有效的算法是什么?

4 个答案:

答案 0 :(得分:3)

您必须在节点上执行topological sort,并按结果顺序访问节点。

这种算法的复杂性是O(| V | + | E |),这是非常好的。你想要遍历所有节点,所以如果你想要一个比这更快的算法,你必须解决它,甚至没有查看所有边缘,这将是危险的,因为一个单一的边缘可能会破坏完全订购。

答案 1 :(得分:1)

这里有一些答案: Good graph traversal algorithm

在这里: http://en.wikipedia.org/wiki/Topological_sorting

通常,在访问节点后,您应该访问其相关节点,但只访问尚未访问过的节点。为了跟踪访问的节点,您需要将节点的ID保存在集合(或映射)中,或者您可以将节点标记为已访问(以某种方式)。

如果您关心拓扑顺序,则必须首先获取节点的所有未遍历链接(“剩余链接”)的集合,并按引用节点的ID排序(通常为:map(节点) -ID - > link-count))。如果你还没有,你可能需要使用类似于上面的方法来构建它。然后,首先访问剩余传入链接计数为零的节点。对于来自该节点的每个链路,减少每个相关节点的剩余链路计数,如果计数达到零,则将相关节点添加到要访问的节点集(或仅访问节点)。

答案 2 :(得分:1)

正如其他答案所述,Topological Sorting可以解决这个问题。

一种非常简单的算法(不是最有效的):

Keep an array (or map) indegree[] where indegree[node]=number of incoming edges of node

while there is at least one node n with indegree[n]=0:
   for each node n in nodes where indegree[n]>0:
      visit(n)
      indegree[n]=-1 # mark n as visited
      for each node x adjacent to n:
          indegree[x]=indegree[x]-1 # its parent has been visited, so one less edge coming into it

答案 3 :(得分:0)

您可以通过仅以零度数在每个节点上运行df来遍历O(N)中的DAG(无任何topsort),因为这将是有效的“起点”。之所以可行,是因为图没有循环,必须存在零个度数节点,并且必须遍历整个图。