在无向图中查找循环与在有向图中查找循环

goo*_*ser 9 algorithm graph

所以我正在阅读Robert Sedgewick的算法第4版.书和在有向图中找到循环的方法不同于在无向图中找到循环的方法.

以下是在无向图中查找循环的示例代码

public class Cycle {
   public boolean[] marked;
   public boolean hasCycle;

   public Cycle(Graph G) {
      marked = new boolean[G.V()]; // G.V() is the number of vertices in the graph G
      for (int s = 0; s < G.V(); ++s) {
         if (!marked[s])
            dfs(G, s, s);
      }
   }

   private void dfs(Graph G, int v, int u) {
      marked[v] = true;
      for (int w : G.adj(v)) //iterate through vertices adjacent to v
         if (!marked[w])
            dfs(G, w, v)
         else if (w != u) hasCycle= true;
   }

   public boolean hasCycle() {
      return hasCycle;
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,当试图在有向图中找到一个循环时,Sedgewick使用一个布尔数组,如果在当前调用堆栈中检查了第i个顶点,则该数组的第i个元素为true.对于检查的每个顶点K,我们检查布尔数组的Kth元素是否为真.如果是,那么我们有一个周期.我的问题是,为什么有必要将该布尔数组用于有向图.我刚刚列出的方法不应该更节省内存吗?这种方法是否仅适用于无向图?为什么?

Rei*_*ica 16

您不能使用相同的算法:上面的算法只是探索图的所有连通组件.如果遇到已标记的顶点,则必须有两个不同的路径才能到达它,并且在无向图中必须有一个循环.如果没有,您可以继续使用下一个连接的组件 - 无需清理刚刚完成的组件.

另一方面,如果您有一个有向图,则到同一顶点的两条不同路径不会形成循环.所以你需要一个不同的算法(例如,你可能需要清理你回溯的任何步骤.)

  • 谢谢,这很有意义。只是想出了一个反例http://i.imgur.com/uBWTZ.png (2认同)