我理解DFS和BFS之间的区别,但是我想知道在选择DFS和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,

其他回答

这在很大程度上取决于搜索树的结构以及解的数量和位置(也就是搜索项)。

If you know a solution is not far from the root of the tree, a breadth first search (BFS) might be better. If the tree is very deep and solutions are rare, depth first search (DFS) might take an extremely long time, but BFS could be faster. If the tree is very wide, a BFS might need too much memory, so it might be completely impractical. If solutions are frequent but located deep in the tree, BFS could be impractical. If the search tree is very deep you will need to restrict the search depth for depth first search (DFS), anyway (for example with iterative deepening).

但这些只是经验法则;你可能需要尝试一下。

我认为在实践中,你通常不会以纯粹的形式使用这些算法。可能会有一些启发式方法,有助于首先探索搜索空间中有希望的部分,或者您可能希望修改搜索算法,以便能够有效地并行化它。

作为程序员,当您处理这个问题时,有一个因素很突出:如果使用递归,那么深度优先搜索更容易实现,因为您不需要维护包含尚未探索的节点的额外数据结构。

如果你在节点中存储“已经访问过”的信息,下面是深度优先搜索非面向图:

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())

与此形成对比的是广度优先搜索,在广度优先搜索中,无论如何都需要为尚未访问的节点列表维护单独的数据结构。

根据DFS和BFS的性质。 例如,当我们要求最短路径时。 我们通常使用bfs,它可以保证“最短”。 但是DFS只能保证我们可以从这一点可以到达那一点,不能保证‘最短’。

来自 http://www.programmerinterview.com/index.php/data-structures/dfs-vs-bfs/

一个BFS的例子

这里有一个BFS的例子。这类似于级别顺序树遍历,其中我们将使用迭代方法的队列(大多数递归将最终使用DFS)。数字表示BFS中节点被访问的顺序:

在深度优先搜索中,从根开始,尽可能地跟随树的一个分支,直到找到要查找的节点或找到叶节点(没有子节点)。如果您选中了一个叶节点,那么您将继续在最近的具有未探索的子节点的父节点上搜索。

DFS的一个例子

下面是一个DFS的示例。我认为二叉树中的后序遍历将首先从叶层开始工作。数字表示DFS中节点被访问的顺序:

DFS和BFS的区别

比较BFS和DFS, DFS的最大优势是它的内存需求比BFS低得多,因为它不需要在每一层存储所有的子指针。根据数据和您正在寻找的内容,DFS或BFS都可能是有利的。

For example, given a family tree if one were looking for someone on the tree who’s still alive, then it would be safe to assume that person would be on the bottom of the tree. This means that a BFS would take a very long time to reach that last level. A DFS, however, would find the goal faster. But, if one were looking for a family member who died a very long time ago, then that person would be closer to the top of the tree. Then, a BFS would usually be faster than a DFS. So, the advantages of either vary depending on the data and what you’re looking for.

另一个例子是Facebook;关于朋友的朋友的建议。我们需要直接的朋友建议我们在哪里可以使用BFS。可能是寻找最短路径或检测周期(使用递归),我们可以使用DFS。

BFS的一个重要优势是,它可以用于寻找未加权图中任意两个节点之间的最短路径。 然而,我们不能用DFS来做同样的事情。