请注意,图表示为邻接列表。
>
保留一个布尔值数组,以跟踪您以前是否访问过节点。如果您没有新的节点可转到(而不是已经转到的节点),那么只需回溯并尝试其他分支。
来自Cormen的CLRS或Skiena的一个:对于无向图中的深度优先搜索,有两种类型的边,树和背。图有圈当且仅当存在后边。
谁能解释一下什么是图的后边,以及以上两种方法之间的区别。
多谢了。
更新:下面是在这两种情况下检测周期的代码。Graph是一个简单的类,为了简单起见,它将所有的图节点表示为唯一的数字,每个节点都有其相邻的相邻节点(g.getAdmindicentNodes(int)):
public class Graph {
private int[][] nodes; // all nodes; e.g. int[][] nodes = {{1,2,3}, {3,2,1,5,6}...};
public int[] getAdjacentNodes(int v) {
return nodes[v];
}
// number of vertices in a graph
public int vSize() {
return nodes.length;
}
}
检测无向图中的循环的Java代码:
public class DFSCycle {
private boolean marked[];
private int s;
private Graph g;
private boolean hasCycle;
// s - starting node
public DFSCycle(Graph g, int s) {
this.g = g;
this.s = s;
marked = new boolean[g.vSize()];
findCycle(g,s,s);
}
public boolean hasCycle() {
return hasCycle;
}
public void findCycle(Graph g, int v, int u) {
marked[v] = true;
for (int w : g.getAdjacentNodes(v)) {
if(!marked[w]) {
marked[w] = true;
findCycle(g,w,v);
} else if (v != u) {
hasCycle = true;
return;
}
}
}
}
public class DFSDirectedCycle {
private boolean marked[];
private boolean onStack[];
private int s;
private Graph g;
private boolean hasCycle;
public DFSDirectedCycle(Graph g, int s) {
this.s = s
this.g = g;
marked = new boolean[g.vSize()];
onStack = new boolean[g.vSize()];
findCycle(g,s);
}
public boolean hasCycle() {
return hasCycle;
}
public void findCycle(Graph g, int v) {
marked[v] = true;
onStack[v] = true;
for (int w : g.adjacentNodes(v)) {
if(!marked[w]) {
findCycle(g,w);
} else if (onStack[w]) {
hasCycle = true;
return;
}
}
onStack[v] = false;
}
}
回答我的问题:
图有圈当且仅当存在后边。后边是从节点到自身(selfloop)或由DFS生成的树中形成循环的一个祖先的边。
上面的两种方法实际上是相同的。然而,这种方法只能应用于无向图。
在无向图中求圈
无向图有圈当且仅当深度优先搜索(DFS)找到指向已访问顶点的边(后边)。
在有向图中求圈
除了访问的顶点外,我们还需要跟踪当前DFS遍历的函数递归堆栈中的顶点。如果我们到达一个已经在递归堆栈中的顶点,那么树中就有一个循环。
更新:工作代码在上面的问题部分。
因此,我为DFS编写了以下代码: 现在,我读到,在一个无向图中,如果当DFS时,它再次返回到同一个顶点,有一个循环。所以我做的是这样,, 但是,我的检查周期函数返回true,即使他们没有周期。那是为什么呢?我的功能有问题吗?没有执行问题,否则我早就调试了,但他们似乎在我的逻辑中有问题。
我对DFS和回溯算法的区别感到困惑。在我看来,回溯只是一个特殊版本的DFS,对吗?
本文向大家介绍JS中string的startwith和indexof两种方法的区别?相关面试题,主要包含被问及JS中string的startwith和indexof两种方法的区别?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: JS中startwith函数,其参数有3个,stringObj,要搜索的字符串对象,str,搜索的字符串,position,可选,从哪个位置开始搜索,如果以posi
我在这里读到一篇关于在有向图中求圈的讨论。现在,OP声称我们需要验证两件事: 从到有一个后沿 在递归堆栈中 为什么我们需要第二次测试?你能举个例子来说明它的必要性吗?
我看到了这篇SO帖子,其中建议在有向图中使用DFS进行循环检测由于回溯而更快。这里我引用该链接: 深度优先搜索比广度优先搜索更节省内存,因为您可以更快地回溯。如果使用调用堆栈,则实现起来也更容易,但这取决于不溢出堆栈的最长路径。 如果你的图是有方向的,那么你不仅要记住你是否访问过一个节点,还要记住你是如何到达的。否则,你可能会认为你已经找到了一个循环,但在现实中,你所拥有的只是两条不同的路径- 为
我正在努力学习如何检测循环。我看到很多使用递归的例子,但我想以迭代的方式实现。这是我的密码 它没有按预期工作 我在这里遗漏了什么逻辑?