繁体   English   中英

使用DFS检查无向图中的循环吗?

[英]Checking for a cycle in an undirected graph using DFS?

因此,我为DFS编写了以下代码:

void dfs (graph * mygraph, int foo, bool arr[]) // here, foo is the source vertex
{
    if (arr[foo] == true)
        return;
    else
    {
        cout<<foo<<"\t";
        arr[foo] = true;
        auto it = mygraph->edges[foo].begin();
        while (it != mygraph->edges[foo].end())
        {
            int k = *it;
            if (arr[k] == false)
            {
                //cout<<k<<"\n";
                dfs(mygraph,k,arr);
                //cout<<k<<"\t";
            }
            it++;
        }
    }
    //cout<<"\n";
}

现在,我阅读了一个无向图,如果在DFS中,它再次返回到同一顶点,则存在一个循环。 因此,我所做的就是

bool checkcycle( graph * mygraph, int foo, bool arr[] )
{

    bool result = false;
    if (arr[foo] == true)
    {
        result = true;
    }
    else
    {
        arr[foo] = true;
        auto it = mygraph->edges[foo].begin();
        while (it != mygraph->edges[foo].end())
        {
            int k = *it;
            result = checkcycle(mygraph,k,arr);     
            it++;
        }
    }
    return result;
}   

但是,我的checkcycle函数即使没有循环也返回true。 这是为什么? 我的功能有问题吗? 没有执行问题,否则我将进行调试,但是在我的逻辑上它们似乎有问题。

请注意,您的函数并没有完全按照您的想象去做。 让我尝试逐步了解这里发生的情况。 假定以下关系:(1,2),(1,3),(2,3)。 我不假设反射性(即(1,2)并不意味着(2,1))。 关系是直接的。

  1. 从节点1开始。将其标记为已访问
  2. 迭代其子项(2和3)
  3. 在节点2中时,递归调用check cycle 此时,2也标记为已访问。
  4. 现在,递归调用将访问3(深度搜索)。 3也标记为已访问
  5. 要求步骤4死返回false
  6. 要求步骤3死返回false
  7. 我们回到步骤2。现在,我们将迭代节点3,该节点已经在步骤4中进行了标记。它仅返回true

您需要一堆访问的节点,或者仅搜索原始节点。 堆栈也将检测子周期(不包括原始节点的周期),但它还会占用更多内存。

编辑:节点堆栈不仅是一堆true / false值,而是一堆节点编号。 如果节点在堆栈中,则已在当前堆栈跟踪中访问过该节点。

但是,还有一种更友好的内存方式:set arr[foo] = false; 随着电话的消失。 像这样:

bool checkcycle( graph * mygraph, int foo, bool arr[], int previousFoo=-1 )
{
    bool result = false;
    if (arr[foo] == true)
    {
        result = true;
    }
    else
    {
        arr[foo] = true;
        auto it = mygraph->edges[foo].begin();
        while (it != mygraph->edges[foo].end())
        {
            int k = *it;

            // This should prevent going back to the previous node
            if (k != previousFoo) {
                result = checkcycle(mygraph,k,arr, foo);
            }

            it++;
        }

        // Add this
        arr[foo] = false;
    }
    return result;
}   

我认为应该足够了。

编辑:现在应该支持无向图。 节点:此代码未经测试

编辑:有关更详尽的解决方案,请参见“ 紧密连接的组件”

编辑:尽管在评论中给出了具体的解决方案,但这个答案是市场接受的。 阅读评论以获取详细信息。

在checkcycle开始之前,arr []中的所有布尔值都设置为false吗?

您确定节点的迭代器不会在遍历的边缘上加倍(因此,无论周期如何,都多次看到起始节点)?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM