我理解DFS和BFS之间的区别,但是我想知道在选择DFS和BFS时应该考虑哪些因素。
比如对于非常深的树避免DFS,等等。
我理解DFS和BFS之间的区别,但是我想知道在选择DFS和BFS时应该考虑哪些因素。
比如对于非常深的树避免DFS,等等。
当前回答
根据DFS和BFS的性质。 例如,当我们要求最短路径时。 我们通常使用bfs,它可以保证“最短”。 但是DFS只能保证我们可以从这一点可以到达那一点,不能保证‘最短’。
其他回答
作为程序员,当您处理这个问题时,有一个因素很突出:如果使用递归,那么深度优先搜索更容易实现,因为您不需要维护包含尚未探索的节点的额外数据结构。
如果你在节点中存储“已经访问过”的信息,下面是深度优先搜索非面向图:
def dfs(origin): # DFS from origin:
origin.visited = True # Mark the origin as visited
for neighbor in origin.neighbors: # Loop over the neighbors
if not neighbor.visited: dfs(neighbor) # Visit each neighbor if not already visited
如果将“已经访问过”的信息存储在单独的数据结构中:
def dfs(node, visited): # DFS from origin, with already-visited set:
visited.add(node) # Mark the origin as visited
for neighbor in node.neighbors: # Loop over the neighbors
if not neighbor in visited: # If the neighbor hasn't been visited yet,
dfs(neighbor, visited) # then visit the neighbor
dfs(origin, set())
与此形成对比的是广度优先搜索,在广度优先搜索中,无论如何都需要为尚未访问的节点列表维护单独的数据结构。
BFS的一个重要优势是,它可以用于寻找未加权图中任意两个节点之间的最短路径。 然而,我们不能用DFS来做同样的事情。
这是一个很好的例子,说明BFS在某些情况下优于DFS。https://leetcode.com/problems/01-matrix/
当正确实现时,两个解决方案都应该访问比当前单元格+1距离更远的单元格。 但DFS效率低,重复访问同一单元,导致复杂度为O(n*n)。
例如,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,
一些算法依赖于DFS(或BFS)的特定属性来工作。例如,用于查找2连接组件的Hopcroft和Tarjan算法利用了这样一个事实,即DFS遇到的每个已经访问过的节点都位于从根节点到当前探索的节点的路径上。
DFS比BFS更节省空间,但可能会深入到不必要的深度。
它们的名字揭示了:如果有很大的广度(即大的分支因子),但深度非常有限(例如有限的“移动”数量),那么DFS可能比BFS更受欢迎。
关于国际发展基金
应该提到的是,有一个不太为人所知的变体,它结合了DFS的空间效率,但(累积)BFS的水平顺序访问,是迭代深化深度优先搜索。该算法对一些节点进行了重访,但只贡献了一个常数因子的渐近差分。