【发布时间】:2013-12-12 22:10:42
【问题描述】:
我遇到了这个SO post,其中建议在有向图中使用 DFS 进行循环检测由于回溯而更快。我在这里引用该链接:
深度优先搜索比广度优先搜索更节省内存,因为您可以更快地回溯。如果您使用调用堆栈,也更容易实现,但这依赖于最长的路径不会溢出堆栈。
此外,如果您的图表是有向的,那么您不仅要记住 如果你访问过一个节点,还有你是如何到达那里的。 否则你可能认为你找到了一个循环,但实际上 你所拥有的只是两条独立的路径 A->B 但这并不意味着 有一条路径 B->A。通过深度优先搜索,您可以标记节点 在您下降时访问并在您回溯时取消标记。
为什么回溯很重要?
有人可以用示例图解释给定A->B 示例中的含义吗?
最后,我有一个DFS 代码用于有向图中的循环检测,它不使用回溯,但仍然在O(E+V) 中检测循环。
public boolean isCyclicDirected(Vertex v){
if (v.isVisited) {
return true;
}
v.setVisited(true);
Iterator<Edge> e = v.adj.iterator();
while (e.hasNext()) {
Vertex t = e.next().target;
// quick test:
if (t.isVisited) {
return true;
}
// elaborate, recursive test:
if (isCyclicDirected(t)) {
return true;
}
}
// none of our adjacent vertices flag as cyclic
v.setVisited(false);
return false;
}
【问题讨论】:
-
if (t.isVisited) { return true; }是不必要的,因为当 isCyclicDirected(t) 被调用时,它首先会检查传入的 Vertex 是否已被访问。 -
@Floegipoky:同意!非常有效的观点!但是算法总体上是正确的吧?
-
不,很遗憾它不正确。但是,如果您在
return false;之前添加了v.setVisited(false);,我想它会是! :) -
@Floegipoky:是的,我刚刚想通了。谢谢你,我正在编辑帖子
-
一般来说,您应该避免修复问题中的代码,因为这往往会使某些(部分或全部)答案无效。在这种情况下,它可能已经够小了。
标签: algorithm depth-first-search backtracking directed-graph cyclic-graph