【问题标题】:Worst Case Time Complexity of Depth First Search深度优先搜索的最坏情况时间复杂度
【发布时间】:2012-08-03 20:12:07
【问题描述】:

我知道这个特定问题的答案是 O(V + E),对于像树这样的图形,这是有道理的,因为每个顶点只被探索一次。

但是假设图中有一个循环。

例如,让我们使用一个有四个顶点 A-B-C-D 的无向图。
A 连接到 B 和 C,B 和 C 都连接到 D。所以总共有四个边。 A->B、A->C、B->D、C->D,反之亦然。

让我们做 DFS(A)。

它将首先探索 B,然后探索 B 的邻居 D 和 D 的邻居 C。之后 C 将没有任何边,所以它会回到 D 和 B,然后是 A。

然后 A 将遍历它的第二条边并尝试探索 C,因为它已经探索过了,所以它不会做任何事情并且 DFS 将结束。

但是在这里顶点“C”已经被遍历了两次,而不是一次。显然,最坏情况的时间复杂度可以与 V 成正比。

有什么想法吗?

【问题讨论】:

  • 我在你的图中没有看到 D->C,所以它应该从 D 开始回溯。所以遍历应该是 A->B->D,A->C。跨度>
  • @Ayos 这是一个无向图,所以因为 C->D 在那里 D->C 也在那里,抱歉表示不正确

标签: algorithm data-structures time-complexity depth-first-search


【解决方案1】:

如果您不维护 visited,用于避免重新访问已访问的节点,则 DFS 不是 O(V+E)。事实上,它不是完整的算法——如果有路径,它甚至可能找不到路径,因为它会陷入无限循环。

请注意,对于无限图,如果您正在寻找从 st 的路径,即使维护访问集,也不能保证完成,因为您可能会卡在无限分支中。

如果您有兴趣保持 DFS 的高效空间消耗优势,同时仍然是完整的 - 您可以使用 iterative deepening DFS,但如果您希望发现整个图而不是路径,它不会轻易解决问题到特定节点。

编辑:设置了visited 的DFS 伪代码。

DFS(v,visited):
  for each u such that (v,u) is an edge:
       if (u is not in visited):
            visited.add(u)
            DFS(u,visited)

很容易看出,当且仅当它尚未被访问时,您才在顶点上调用递归,因此答案在顶点和边的数量上确实是线性的。

【讨论】:

  • 我正在使用已访问集,这就是 BFS 在图中从 C 撤退的原因,因为它的两个邻居 (A,D) 都已被探索/访问过。但是当输出程序返回到起始节点 A 时,它将再次检查这个顶点 C,但是由于它已经被访问过,它将被忽略并且循环将结束.. 所以 C 被访问了两次 IMO 如果可能的话,请绘制此图在相同的波长
  • @Batman:我添加了一个带有 DFS 的伪代码,它维护一个 visited 集合并最多访问每个顶点一次,我希望它能让你清楚。
【解决方案2】:

您可以访问图形的每个顶点和边的次数为常数,仍然是 O(V+E)。另一种看待它的方式是,成本计入边缘,而不是顶点。

【讨论】:

  • 你能说得更具体点吗,或者你能在我在问题中显示的图表的上下文中告诉我(A、B、C、D)
猜你喜欢
  • 2016-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多