在有向图中使用DFS进行循环检测是否绝对需要回溯?

 焦鹏666_479 发布于 2023-02-11 10:32

我发现了这篇SO帖子,建议在有向图中使用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 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;
}

Dukeling.. 5

为什么需要回溯:

A -> B
^ \
|  v
D <- C

如果你去A -> B,你没有回溯,你会停在那里,你将找不到周期.

你的算法确实回溯了.你只是将它包装在递归中,所以它可能看起来不像你期望的那样.你为其中一个邻居递归,如果这没有找到一个循环,那个呼叫会返回,你会尝试其他邻居 - 这就是回溯.

为什么你需要记住你到达目的地的方式:

A -> B
  \  ^
   v |
     C

上面的图表没有周期,但如果你去A -> B,那么A -> C -> B,你会认为如果你不记得路径.

如链接帖子中所述,您可以在返回代码之前将被访问标志设置为false(我看到您现在已经完成了) - 这将用作记住路径.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有