图形搜索:广度优先与深度优先


78

搜索图时,有两种简单的算法:广度优先深度优先(通常通过将所有邻接图节点添加到队列(广度优先)或堆栈(深度优先)来完成)。

现在,一个相对于另一个有什么优势吗?

我能想到的:

  • 如果您希望数据在图表内很远,那么深度优先可能会更早找到它,因为您可以非常快速地进入图表的较深部分。
  • 相反,如果您希望数据在图表中靠前很远,那么广度优先的结果可能会更早。

我有什么想念的吗?还是主要取决于个人喜好?

Answers:


43

我想引用从堆栈溢出的答案hstoerr它很好地涵盖了问题:

这在很大程度上取决于搜索树的结构以及解决方案的数量和位置
如果您知道解决方案离树的根并不远,那么广度优先搜索(BFS)可能更好。如果树很深并且解决方案很少,则深度优先搜索(DFS)可能永远存在,但是BFS可能更快。如果树很宽,则BFS可能需要过多的内存,因此可能是完全不切实际的。如果解决方案很常见但位于树的深处,则BFS可能不切实际。如果搜索树非常深,则无论如何都需要限制深度优先搜索(DFS)的搜索深度(例如,使用迭代加深)。

但是,这些只是经验法则。您可能需要进行实验。

RafałDowgird也指出:

有些算法取决于DFS(或BFS)的特定属性才能起作用。例如,用于查找2连接的组件的Hopcroft和Tarjan算法利用了以下事实:DFS遇到的每个已经访问的节点都在从根到当前探索的节点的路径上。


5
我不明白为什么这个答案有27个upvotes,它是完全的其他2个回答,它的方式是简单地左右的总体思路合并...
NBRO

37

在我们的多核世界中重要的一点是:BFS易于并行化。从直觉上讲,这是合理的(为每个孩子分配线程),事实也是如此。因此,如果您有可以利用并行性的情况,那么BFS是可行的方法。


8
如果DFS在给定的设置中其他方面是有利的,则可以应用BFS,直到产生足够的线程并继续使用DFS。更具体地说,您可以执行DFS,并且每当您下降而没有足够的线程时,就为下一个兄弟生成一个。
拉斐尔

这个答案不值得20票赞成。问题是关于这两种算法的一般用途,而不是特定用途。
nbro,2015年

31

(我将其设置为社区Wiki。请随时进行编辑。)

如果

  • b
  • d
  • HdH

然后

  • ØbHØH
  • ØbdØbd
  • ØbdØd

选择理由

  • DFS
    • 反正一定要看整棵树
    • d
    • 不在乎答案是否最接近根
  • BFS
    • 答案接近根源
    • 您想要最接近根的答案
    • 有多个内核/处理器
  • IDDFS
    • 您想要BFS,没有足够的内存,但是稍微慢一点是可以接受的

IDDFS = 迭代加深深度优先搜索


1
这是一个很好的答案。我注意到虽然这个问题是关于图形的,但这个答案是针对树木的。一棵树当然是一幅图,它可能是可以替换的单词...但是h“树的高度”呢?这直接转化为“图形的高度”吗?
user2023370 '16

使用IDDFS的另一个原因是,根据您要如何使用它,在每次迭代之后,您都可以得到一个可能的答案(如果要搜索最大值或最小值)。这意味着,如果您的回答“足够好”,您可以及早退出算法,或者您可以根据用户输入退出(例如,使用IDDFS来寻找最佳解决方案的象棋引擎,但由于玩家移动棋子而中断了)。
jedd.ahyoung

要添加的另一点是DFS使用堆栈,而BFS使用队列。
Karthik Balaguru

17

无限图可能是一个场景(除了已经提到过的最短路径之外),您可能不得不选择另一个以获得正确的程序:

例如,如果我们考虑一棵树,其中每个节点都有有限数量的子节点,但是树的高度是无限的,则DFS可能永远找不到您要查找的节点-它只会继续访问它的每个节点的第一个子节点会看到,因此,如果您要寻找的不是父母的第一个孩子,它将永远不会到达那里。但是,保证BFS在有限时间内找到它。

同样,如果我们考虑一棵树,其中每个节点都有无限数量的子节点,但树的高度有限,则BFS可能不会终止。它只会访问根节点的子节点,并且如果您要查找的节点是其他节点的子节点,则不会到达该节点。在这种情况下,保证DFS在有限时间内找到它。


7
值得注意的是,这两种方法都只能生成无限图的半决策算法。您不能在有限时间内确定某个元素不在树中(显然)。对于实际应用,请注意(概念上)可以定义无限的数据结构(请参见第3.4节)!
拉斐尔

15

广度优先和深度优先当然具有相同的最坏情况行为(所需的节点是找到的最后一个)。我怀疑,如果您没有有关图的信息,那么在平均情况下也是如此。

广度优先搜索的一个不错的好处是,它可以找到可能感兴趣或不感兴趣的最短路径(就最少的边缘而言)。

如果您的平均节点等级(邻居数)相对于节点数高(即图形密集),则广度优先将有大量队列,而深度优先将具有较小的堆栈。在稀疏图中,情况是相反的。因此,如果内存是一个限制因素,则当前图形的形状可能必须告知您选择的搜索策略。


队列的长度(以bfs为单位)和堆栈的高度(以dfs为单位)在很大程度上取决于实现。如果在dfs的情况下,您总是在堆栈上扩展整个邻居,那么它会增长很多,尤其是在图形密集时。仅推送引用,该引用告诉dfs从递归返回时从何处继续可以节省大量空间。
乌里2012年

3

以上所有内容都是正确的,但值得注意的是,BFS和DFS根据它们遍历树的顺序创建自己的树。这些树中的每一个都有其自己的属性,在某些问题中很有用。

例如,原始图中不在BFS树中的所有边都是交叉边;BFS树的两个分支之间的边。原始图中不在DFS树中的所有边都是后边;连接DFS树的一个分支中的两个顶点的边。此类属性对于诸如特殊着色等问题可能很有用。


1

DFS和BFS树都有自己的独特属性,这些属性可以为您提供有关图形的更多有用信息。例如,对于单个DFS,您可以执行以下操作:

  • 查找桥和铰接点(用于无向图)
  • 循环检测
  • 查找牢固连接的组件(Tarjan算法)

使用BFS,您可以找到源节点和图中任何其他节点之间的最短路径。

CLRS中的“图形算法”一章很好地总结了DFS和BFS的这些属性。


-2

我认为,以这样一种方式来编写它们都是很有趣的:仅通过切换几行代码就可以为您提供一种算法或另一种算法,这样您便会发现您的视差不像刚开始时那样强大。

我个人喜欢将BFS解释为淹没景观:低海拔地区将首先被淹没,然后高海拔地区才会被淹没。如果您像我们在地理书籍中所看到的那样将景观高度想象为等值线,则很容易看到BFS同时填充同一等值线下的所有区域,就像物理学中那样。因此,将海拔高度解释为距离或成比例的成本可以很好地直观了解该算法。

考虑到这一点,您可以轻松地根据广度优先搜索的思想来轻松找到最小的生成树,最短的路径以及许多其他最小化算法。

我还没有看到DFS的任何直观解释(仅是关于迷宫的标准解释,但它不如BFS 1和洪水泛滥),因此对我来说,BFS似乎与上述物理现象更好地关联,而DFS与理性系统上的选择困境有更好的关联(即,人们或计算机决定在国际象棋游戏中走出困境或走出迷宫)。

因此,对我而言,区别在于哪种自然现象最适合其在现实生活中的传播模型(横向)。


2
欢迎光临本站!但是,我真的不知道这如何回答问题。这似乎是您对BFS和DFS的一般感觉和直觉,但问题不是在询问感觉和直觉:它是在询问优点和缺点。您的答案似乎根本没有解决。
David Richerby '16

与问题最相关的部分是关于修改算法以找到最小的生成树,最短路径等,并说BFS可复制某些自然现象,而DFS可复制决策树
user5193682,2013年

1
问题不是问与BFS和DFS有什么关系。它不是在寻找找到生成树或最短路径或如何“重现自然现象”的问题。
大卫·里希比

它要求优势。如果一个人可以对一个物理现象进行建模而其他人则不能,那么如果您需要对这种现象进行建模,那么这是一个优势。我认为您在解释“优势”一词时会
遵循
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.