此示例中DFS与BFS之间的区别?

时间:2018-07-01 05:11:43

标签: algorithm graph-theory depth-first-search breadth-first-search

阅读DFS上打印输出的示例后,我有点困惑 两种DFS方法都以不同的方式出现,尽管两者都被称为DFS。

事实上,DFS递归方法以与输出相同的方式打印输出 BFS。那有什么区别呢?这里给出的递归方法不是DFS的示例吗?

enter image description here

使用堆栈

// Iterative DFS using stack
    public  void dfsUsingStack(Node node)
    {
        Stack<Node> stack=new  Stack<Node>();
        stack.add(node);
        node.visited=true;
        while (!stack.isEmpty())
        {
            Node element=stack.pop();
            System.out.print(element.data + " ");

            List<Node> neighbours=element.getNeighbours();
            for (int i = 0; i < neighbours.size(); i++) {
                Node n=neighbours.get(i);
                if(n!=null && !n.visited)
                {
                    stack.add(n);
                    n.visited=true;

                }
            }
        }
    }

输出为       40,20,50,70,60,30,10

递归方法

// Recursive DFS
    public  void dfs(Node node)
    {
        System.out.print(node.data + " ");
        List neighbours=node.getNeighbours();
        node.visited=true;
        for (int i = 0; i < neighbours.size(); i++) {
            Node n=neighbours.get(i);
            if(n!=null && !n.visited)
            {
                dfs(n);
            }
        }
    }

输出为        40,10,20,30,60,50,70与BFS

下的输出相同

那有什么区别?

2 个答案:

答案 0 :(得分:2)

至少在DFS算法的规范定义中,第一种方法根本不是DFS。仅仅是BFS,其中有人用堆栈替换了队列。但是,从某种意义上来说,此实现足以“模仿” DFS,因为它可以发现类似于DFS的图顶点。如果愿意,可以将其称为“伪DFS”,因为它类似于DFS的发现顺序,但是规范的DFS算法远不止于此。

规范的DFS不仅遵循深度优先的顶点发现顺序,而且还会生成某些“未发现”顺序,某些回溯顺序(即经典Dijkstra命名法中的"gray" vertex becomes "black" vertex时) 。在第一个实现中,规范DFS的这一重要功能不存在(或者不可能以任何合理的方式实现)。

同时,第二种方法是经典DFS算法的显式递归实现。

在任何情况下,无论是真实DFS还是伪DFS,都没有访问顶点的“一个真实顺序”。两种实现方式都可以产生相同的顶点访问顺序。在您的情况下,没有人会简单地确保这一点。输出的差异是由以下简单事实造成的:前一个实现以反向顺序(从最后到第一个)访问邻居。首先将所有邻居都推入堆栈,然后逐个弹出以进行访问。堆栈的后进先出行为是产生反转的原因。同时,后一种实现以邻居的前进顺序(从头到尾)访问邻居。

如果您将后一种实现中的循环替换为

for (int i = neighbours.size() - 1; i >= 0; --i) 

在两种实现中,您最终都应使用相同的访问顺序(相同的输出)。

答案 1 :(得分:2)

虽然最终结果(路径)可能相同,但是bfs和dfs(不是发布的特定实现)之间的根本区别在于搜索机制。
一个明显的例子是只有一条路径存在的情况。在这种情况下,任何好的搜索算法(无论是dfs,bfs还是其他算法)最终都会找到该路径。
如果存在多个路径,则bfs和dfs可能会找到相同或不同的路径。 bfs的特征之一是它找到最短的路径。
搜索机制的核心区别在于bfs在所有方向上均等地探索(因此称为“广度”),而dfs在整个方向上(因此均称“深度”)探索一个(通常是随机的)方向,如果找不到解,则“回溯”。
有很多资源可以直观地显示bfs和dfs,例如 this个。
这是我创建的用于演示和测试遍历算法的工具的屏幕截图:

enter image description here

通过查看代表探索节点的灰色点,您可以看到bfs的性质,类似于水淹。

enter image description here