我有一个大的(100,000多个节点)定向非循环图(DAG),并且希望按顺序在每个节点上运行“访问者”类型函数,其中顺序由图中的箭头定义。即节点的所有父节点都保证在节点本身之前被访问。
如果两个节点没有直接或间接地相互引用,那么我不关心它们被访问的顺序。
最有效的算法是什么?
答案 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),因为这将是有效的“起点”。之所以可行,是因为图没有循环,必须存在零个度数节点,并且必须遍历整个图。