我理解DFS和BFS之间的区别,但是我想知道在选择DFS和BFS时应该考虑哪些因素。
比如对于非常深的树避免DFS,等等。
我理解DFS和BFS之间的区别,但是我想知道在选择DFS和BFS时应该考虑哪些因素。
比如对于非常深的树避免DFS,等等。
当前回答
当树的宽度非常大,深度很低时,使用DFS作为递归堆栈不会溢出。当宽度很低而深度很大时使用BFS遍历树。
其他回答
我认为这取决于你所面临的问题。
简单图上的最短路径-> BFS 所有可能的结果-> DFS 在图上搜索(将树,martix也视为图)-> 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。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遍历树。