我知道这个问题在本论坛和互联网上的其他地方都被多次询问过。但是在你伸出爪子攻击我之前,请耐心等待。
我是一个新手学习图。作为我练习的一部分,我在这里给Graph类中添加一个方法hasCycle() http://homepage.cs.uiowa.edu/~sriram/21/fall05/ExamplePrograms/ReaderFiles/Chap13/dfs/dfs.java
我的方法,按照此论坛中的建议Finding a cycle in an undirected graph vs finding one in a directed graph进行DFS。
但我正在努力如何使用第一个链接中的现有dfs方法来实现它。
到目前为止我的方法是:
public boolean hasCycle(int start)
{
vertexList[start].wasVisited = true;
for(int j = 0; j < MAX_VERTS; j++)
{
if(adjMat[start][j]==1 && vertexList[j].wasVisited==true)
return true;
else if(adjMat[start][j]==1 && vertexList[j].wasVisited==false)
{
vertexList[start].wasVisited == true;
hasCycle(j);
}
}
return false;
}
我有两个问题: 首先,当我在DFSApp类而不是行中调用hasCycle()时,我陷入无限递归 theGraph.dfs(); 第二,我没有使用我的作业所需的给定dfs()。
对于我在这里做错了什么,我们会理解正确道路的任何方向。
现在我只专注于在不使用dfs()的情况下实现正确的单独的hasCycle()方法。
答案 0 :(得分:10)
注意:此答案假设图形是无向(换句话说,邻接矩阵是对称的)。对于有向图,答案更复杂。
您需要检查从hasCycle(j)
的递归调用返回的值。例如:
if (hasCycle(j))
return true;
如果您点击一个循环并将true一直返回到顶层,这将“展开堆栈”。
此外,虽然这只是一个小问题并且不会真正影响功能,但在递归调用hasCycle(j)
之前的行有两个问题。首先,它应该是一个单一的等号,而不是一个双。其次,它实际上是多余的,因为在hasCycle(j)
的递归调用中发生的第一件事是节点j
将被标记为已访问。
考虑到这一点,这里是代码的简化:
public boolean hasCycle(int start)
{
vertexList[start].wasVisited = true;
for (int j = 0; j < MAX_VERTS; j++) {
if (adjMat[start][j] == 1 && (vertexList[j].wasVisited || hasCycle(j)))
return true;
}
return false;
}
在@mehrmoudi的评论后编辑:
哇。以上不太正确!抱歉!!在下面的修复程序中,我添加了parent
参数。
public boolean hasCycle(int start, int parent)
{
vertexList[start].wasVisited = true;
for (int j = 0; j < MAX_VERTS; j++) {
if (j != parent && adjMat[start][j] == 1 && (vertexList[j].wasVisited || hasCycle(j, start)))
return true;
}
return false;
}