在有向图的广度优先搜索(可能的循环)中,当一个节点退出队列时,其所有尚未访问的子节点都将进入队列,并且该过程将继续,直到队列为空为止。
有一次,我以另一种方式实现它,其中节点的所有子节点都排队,当节点出队时,检查访问状态。如果之前访问过正在退出队列的节点,则该节点将被丢弃,并继续到队列中的下一个节点。
但结果是错的。维基百科还说
深度优先搜索。。。。。。非递归实现类似于广度优先搜索,但在两个方面与之不同:它使用堆栈而不是队列,它延迟检查顶点是否已被发现,直到顶点从堆栈中弹出,而不是在推送顶点之前进行此检查。
然而,我无法理解到底有什么不同。为什么在弹出项目时深度优先搜索检查,而在排队前广度优先搜索必须检查?
DFS检查节点是否在解队列时被访问,因为它可能在“更深”级别被访问。例如:
A--B--C--E
| |
-------
如果我们从A开始,那么B和C将被放在堆栈上;假设我们把它们放在堆栈上,那么B将首先被处理。当B现在被处理时,我们想向下到C,最后到E,如果我们从A发现C时将C标记为已访问,则不会发生这种情况。现在,一旦我们从B开始,我们会找到尚未访问的C,并再次将其放在堆栈上。在我们处理完E之后,堆栈上的所有C条目都需要被忽略,标记为visited将为我们提供帮助。
正如@PeterdeRivaz所说,对于BFS来说,无论我们在排队还是退出排队时检查节点是否被访问,这都不是正确性的问题,而是效率的问题。
假设您有一个图形:
A---B---E
| |
| |
C---D
您可以从A中搜索DFS。
如果使用深度优先搜索(假设子节点的顺序),您会期望它搜索节点A、B、D、C、E。
但是,如果您在将节点放置到堆栈之前将其标记为访问过的节点,那么您将访问A,B,D,E,C,因为当我们检查A时,C被标记为访问过的节点。
在某些应用程序中,您只想访问所有连接的节点,这是一种完全有效的方法,但从技术上讲,这不是深度优先搜索。
在广度优先搜索中,您可以在推送到队列之前或之后将节点标记为已访问。但是,由于队列中不会出现大量重复节点,因此在检查之前进行检查更为有效。
我不明白为什么你的BFS代码在这种情况下失败,也许如果你发布代码,它会变得更清晰?
主要内容:深度优先搜索(简称“深搜”或DFS),广度优先搜索,总结前边介绍了有关图的 4 种存储方式,本节介绍如何对存储的图中的顶点进行遍历。常用的遍历方式有两种: 深度优先搜索和 广度优先搜索。 深度优先搜索(简称“深搜”或DFS) 图 1 无向图 深度优先搜索的过程类似于树的先序遍历,首先从例子中体会深度优先搜索。例如图 1 是一个无向图,采用深度优先算法遍历这个图的过程为: 首先任意找一个未被遍历过的顶点,例如从 V1 开始,由于 V1 率先访问过了,所以
我正在研究BFS算法,我有一个关于如何将相邻节点插入队列的问题。 例如,假设我们正在处理一个无向图,我们希望执行BFS来输出图的内容,那么我们如何知道在从队列中取出一个初始节点后,相邻节点以什么顺序插入到队列中呢?还有,有没有办法修改邻居节点插入队列的方式? 任何帮助都将不胜感激,谢谢。
最近,我在Stackoverflow中问了一个关于从图构建DFS树的问题,并了解到它可以通过使用状态单子简单地实现。 haskell中的DFS 虽然DFS要求仅跟踪访问的节点,以便我们可以使用“设置”或“列表”或某种线性数据结构来跟踪访问的节点,但BFS需要“访问的节点”和“队列”数据结构来完成。 我的BFS伪代码是 从伪代码中可以推断,我们每次迭代只需要做3个过程。 从队列中取出点 将该点的所有
遍历顶点的每个相邻边的时间复杂度是,例如,,其中是相邻边的数量。因此,对于顶点数,时间复杂度变为=,其中是图中的边总数。既然从队列中移除和添加顶点是,为什么它会作为添加到BFS的总体时间复杂度中?
本文向大家介绍什么是广度优先搜索?相关面试题,主要包含被问及什么是广度优先搜索?时的应答技巧和注意事项,需要的朋友参考一下 类似树的按层遍历,其过程为:首先访问初始点Vi,并将其标记为已访问过,接着访问Vi的所有未被访问过可到达的邻接点Vi1、Vi2……Vit,并均标记为已访问过,然后再按照Vi1、Vi2……Vit的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依此类推,直到图
在继续使用其他图算法之前,让我们分析广度优先搜索算法的运行时性能。首先要观察的是,对于图中的每个顶点 $$|V|$$ 最多执行一次 while 循环。因为一个顶点必须是白色,才能被检查和添加到队列。这给出了用于 while 循环的 $$O(V)$$。嵌套在 while 内部的 for 循环对于图中的每个边执行最多一次,$$|E|$$。原因是每个顶点最多被出列一次,并且仅当节点 u 出队时,我们才检