Recursion 如何在迭代DFS中检测有向图中的圈?

Recursion 如何在迭代DFS中检测有向图中的圈?,recursion,depth-first-search,directed-graph,Recursion,Depth First Search,Directed Graph,我当前的项目具有一组具有输入和输出的节点。每个节点都可以获取其输入值并生成一些输出值。这些输出可以用作其他节点的输入。为了最小化所需的计算量,在应用程序启动时检查节点依赖关系。当更新节点时,它们将按照相互依赖的相反顺序进行更新 也就是说,节点类似于一个有向图。我使用迭代DFS(无递归以避免大型图中的堆栈溢出)来计算依赖项并创建更新节点的顺序 我还想避免图中的循环,因为循环依赖关系会破坏更新程序算法并导致永远运行的循环 有递归方法通过跟踪递归堆栈上的节点来查找具有DFS的循环,但是有没有迭代的方法

我当前的项目具有一组具有输入和输出的节点。每个节点都可以获取其输入值并生成一些输出值。这些输出可以用作其他节点的输入。为了最小化所需的计算量,在应用程序启动时检查节点依赖关系。当更新节点时,它们将按照相互依赖的相反顺序进行更新

也就是说,节点类似于一个有向图。我使用迭代DFS(无递归以避免大型图中的堆栈溢出)来计算依赖项并创建更新节点的顺序

我还想避免图中的循环,因为循环依赖关系会破坏更新程序算法并导致永远运行的循环


有递归方法通过跟踪递归堆栈上的节点来查找具有DFS的循环,但是有没有迭代的方法?然后,我可以将循环搜索嵌入到主依赖项解析器中,以加快速度。

尝试使用时间戳。在节点上添加元时间戳并将其设置为零

先前的答复(不适用):

开始搜索时,递增或获取时间戳。那么,什么时候? 访问节点时,将其与当前搜索时间戳进行比较。如果是 是一样的,那么你已经找到了一个循环。如果没有,则设置戳记 到目前为止

下一次搜索,再次递增

好的,我假设您正在执行DFS搜索:

  • 将根节点添加到堆栈(用于搜索)和向量(用于更新)
  • 弹出堆栈并将当前节点的子节点添加到堆栈和向量中
  • 循环,直到堆栈为空
  • 反向迭代向量并更新值(通过引用子节点)
问题:循环将导致将同一组节点添加到堆栈中

解决方案1:在添加到DFS搜索堆栈之前,使用布尔/时间戳查看节点是否已被访问。这将消除循环,但不会解决它们。你可以吐出一个错误并退出

解决方案2:使用时间戳,但每次弹出堆栈时都会增加时间戳。如果子节点设置了时间戳,并且该时间戳小于当前时间戳,则您已经找到了一个循环。这是踢球的人。向后迭代这些值时,可以检查子节点的时间戳,以查看它们是否大于当前节点。如果小于,则找到了一个循环,但可以使用默认值


事实上,我认为解决方案1可以用同样的方法解决,即在更新值时从不跟随多个子节点,并在开始时将所有节点设置为默认值。解决方案2将在评估图形时向您发出警告,而解决方案1仅在创建向量时向您发出警告。

在线上有大量循环检测算法可用。最简单的是Dijkstra算法的扩充版本。您维护一个已访问节点的列表以及到达该节点的成本。在您的设计中,将“成本”替换为到达目的地的路径

在算法的每次迭代中,您都会抓取“活动”列表中的下一个节点,并查看图形中紧随其后的每个节点(即其每个依赖项)。如果该节点在“已访问”列表中,则有一个循环。您在Get here中维护的
路径
显示了循环路径


这足以让你移动吗?

这种方法也可以称之为圆:一个是起始节点。A依赖于B和C。B和C都依赖于D。还是我遗漏了什么?我理解你的方法是“访问”标志的替代方法。这是一个很好的观点。我假设您正在对依赖项节点进行排队,并通过弹出队列前端(DFS)来处理它们。然而,您似乎也希望以相反的方式更新它们。需要更新答案…我想更新它们,这样如果A依赖于B,B就会更新,然后A。所以基本上把它们放在堆栈上(是的,可以称之为“反向队列”)。该堆栈被保存,然后馈送到更新程序线程。我不会在树遍历期间运行更新。一个循环是这样的:一个是开始节点。A依赖于B。B依赖于C。C依赖于A。这种依赖关系不可能解决,所以我需要确定这种情况。