如何查找图表是否有周期?

时间:2013-10-29 06:09:59

标签: java algorithm graph depth-first-search

我知道这个问题在本论坛和互联网上的其他地方都被多次询问过。但是在你伸出爪子攻击我之前,请耐心等待。

我是一个新手学习图。作为我练习的一部分,我在这里给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()方法。

1 个答案:

答案 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;
}