当前位置: 首页 > 知识库问答 >
问题:

深度优先搜索是否会产生冗余?

闻华容
2023-03-14

我试图理解维基百科上规范的DFS伪代码(http://en.wikipedia.org/wiki/Depth-first_search)--特别是使用堆栈的非递归实现。

在BFS中,您在将节点推送到队列之前检查它是否已经被探索过,这保证了不会有节点被多次推送到队列上。但是在DFS中,只有当您将节点从堆栈中弹出时,才会检查它是否已经被探索。这似乎是故意的,正如维基百科页面所说:“[DFS]推迟检查是否发现顶点,直到顶点从堆栈中弹出,而不是在推动顶点之前进行检查。”

但是这种延迟似乎会导致节点被多次推送到堆栈上。例如,考虑节点1指向节点2,节点3指向节点4,以此类推,直到节点100的图。这些节点中的每一个都指向节点0。

考虑将维基百科DFS算法应用于此图,节点1作为起始状态。首先,节点0将被推送到堆栈上。然后将推送节点2。接下来,节点2将从堆栈中弹出,由于尚未对其进行探索,其子节点将被推到堆栈上(而不检查它们是否已添加到堆栈中!)。节点2的子节点是节点0和节点3。接下来,将展开节点3,将节点0和节点4推到堆栈上。这将继续,直到堆栈中填满100个节点0。

我的问题是:如果DFS产生这种冗余,它为什么会延迟检查,从而与BFS不同?

共有3个答案

龚彬
2023-03-14

我认为你把维基百科算法看得过于字面意思,而不是思考访问/发现一个节点意味着什么。在BFS中,您也可以将节点的所有子节点/相邻节点推送到队列中,但是您必须丢弃已经发现的节点;DFS也是如此。

在BFS和DFS中,您可以选择:

  1. 不推送已发现的节点。或

BFS和DFS之间的唯一区别在于,您将进入BFS中的堆栈,而不是DFS中的队列。

薛弘阔
2023-03-14

我的错,我认为你在最后一句提出的问题是关于DFS的。。。在这个特定的实现中,向堆栈推送确实是多余的,并且可以通过在“推送”之前添加(如果未访问)条件来轻松避免。

也就是说,它不会改变摊销复杂性O(|E||V|)

尉迟鑫鹏
2023-03-14

你是对的,在维基百科的非递归DFS实现中,每个顶点将被放入堆栈中的次数与传入边的数量相同。

但我认为这不是有意的。您可以看到,这里的递归实现取自Cormen等人的“数据结构和算法简介”。这本书可以被认为比非递归DFS伪代码的源代码更“规范”。你们可以看到,在深入递归之前,目标顶点已经被检查过了。这似乎更合理。

总之,我认为维基百科的实现中存在非关键性缺陷。不盲目相信“正典”通常是一个好办法。

 类似资料:
  • 主要内容:深度优先搜索(简称“深搜”或DFS),广度优先搜索,总结前边介绍了有关图的 4 种存储方式,本节介绍如何对存储的图中的顶点进行遍历。常用的遍历方式有两种: 深度优先搜索和 广度优先搜索。 深度优先搜索(简称“深搜”或DFS) 图 1 无向图 深度优先搜索的过程类似于树的先序遍历,首先从例子中体会深度优先搜索。例如图 1 是一个无向图,采用深度优先算法遍历这个图的过程为: 首先任意找一个未被遍历过的顶点,例如从 V1 开始,由于 V1 率先访问过了,所以

  • 本文向大家介绍深度优先搜索,包括了深度优先搜索的使用技巧和注意事项,需要的朋友参考一下 图遍历是按某种系统顺序访问图的所有顶点的问题。遍历图主要有两种方法。 广度优先搜索 深度优先搜索 深度优先搜索(DFS)算法从顶点v开始,然后遍历到之前未访问过的相邻顶点(例如x),并将其标记为“已访问”,然后继续处理x的相邻顶点,依此类推。 如果在任何一个顶点上遇到所有相邻顶点都被访问过,则它将回溯直到找到具

  • 本文向大家介绍什么是深度优先搜索?相关面试题,主要包含被问及什么是深度优先搜索?时的应答技巧和注意事项,需要的朋友参考一下 如算法名称那样,深度优先搜索所遵循的搜索策略是尽可能“深”地搜索树。它的基本思想是:为了求得问题的解,先选择某一种可能情况向前(子结点)探索,在探索过程中,一旦发现原来的选择不符合要求,就回溯至父亲结点重新选择另一结点,继续向前探索,如此反复进行,直至求得最优解。深度优先搜索

  • 3. 深度优先搜索 现在我们用堆栈解决一个有意思的问题,定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线

  • 深度优先搜索的一般运行时间如下。 dfs 中的循环都在 $$O(V)$$ 中运行,不计入dfsvisit 中发生的情况,因为它们对图中的每个顶点执行一次。 在dfsvisit 中,对当前顶点的邻接表中的每个边执行一次循环。 由于只有当顶点为白色时,dfsvisit 才被递归调用,所以循环对图中的每个边或 $$O(E)$$ 执行最多一次。 因此,深度优先搜索的总时间是 $$O(V + E)$$。

  • 骑士之旅是深度优先搜索的特殊情况,其目的是创建最深的第一棵树,没有任何分支。更一般的深度优先搜索实际上更容易。它的目标是尽可能深的搜索,在图中连接尽可能多的节点,并在必要时创建分支。 甚至可能的是,深度优先搜索将创建多于一个树。当深度优先搜索算法创建一组树时,我们称之为深度优先森林。与广度优先搜索一样,我们的深度优先搜索使用前导链接来构造树。此外,深度优先搜索将在顶点类中使用两个附加的实例变量。新