广度优先搜索和深度优先搜索

Posted

技术标签:

【中文标题】广度优先搜索和深度优先搜索【英文标题】:Breadth First Search and Depth First Search 【发布时间】:2011-01-31 02:48:26 【问题描述】:

谁能提供一个关于 BFS 和 DFS 及其实现的简单解释的链接?

【问题讨论】:

【参考方案1】:

使用 dfs 和 bfs 进行图遍历。

在c++ 和python 中。

【讨论】:

【参考方案2】:

这里有几个链接可以查看:

Breadth-first search

BFS 是一种不知情的搜索方法,旨在通过系统地搜索每个解决方案来扩展和检查图形或序列组合的所有节点。换句话说,它会在找到目标之前彻底搜索整个图或序列而不考虑目标。

Depth-first search

形式上,DFS 是一种不知情的搜索,它通过扩展出现的搜索树的第一个子节点来进行,从而越来越深,直到找到目标节点,或者直到它遇到没有子节点的节点。然后搜索回溯,返回到最近没有完成探索的节点

它们不仅包含关于如何在应用程序中实现的很好的解释,还包含一些算法伪代码。

【讨论】:

【参考方案3】:

假设你有一棵树,如下所示:

这可能有点令人困惑,因为 E 既是 A 又是 F 的孩子,但它有助于说明深度优先搜索的深度。深度优先搜索搜索尽可能深的树(因此称为深度)。所以从左到右的遍历将是 A、B、D、F、E、C、G。

广度优先搜索首先评估所有孩子,然后再继续到孩子的孩子。所以同一棵树会去 A、B、C、E、D、F、G。

希望这会有所帮助。

【讨论】:

那不是一棵树。那是一个有向无环图。 @ThomasEding 你说它不是树是对的,但说它是一个有向无环图*(DAG)是错误的。事实上,如果它是一个*DAG,它就会是一个。他这里描述的其实是一个无向循环图【参考方案4】:

Breadth First Search/Depth First Search Animations

【讨论】:

【参考方案5】:

您可以在 wiki 上找到所有内容:

BFS 和DFS

这个link 也很有用。如果你想要一个实现去:c++ boost library: DFS

【讨论】:

【参考方案6】:

假设您有以下结构:

格式:节点[儿童] A B C D] B [E F] C [G] D [] E [] F [] G []

在访问子节点之前,广度优先搜索会先访问节点的所有子节点。这是上述结构的伪代码和解决方案:

1. 排队根节点。 2.出列和输出。如果队列为空,请转到步骤 5。 3. 将出队节点的子节点入队。 4. 转到步骤 2。 5. 完成 两个队列:(Active Node) [Output] [Working Set] 从根开始: ( ) [] [一种] (A) [A] [B C D] (B) [A B] [C D E F] (C) [A B C] [D E F G] (D) [A B C D] [E F G] (E) [A B C D E] [F G] (F) [A B C D E F] [G] (G) [A B C D E F G] [] 完毕

深度优先搜索首先访问树的最低级别(最深的孩子)。深度优先搜索有两种类型:前序和后序。这只是在将节点添加到输出时(访问它还是离开它)有所不同。

var rootNode = 结构.getRoot(); var preOrder = new Array(); var postOrder = new Array(); 功能深度优先(根节点) // 预购 preOrder[ preOrder.length ] = rootNode; for( var child in rootNode ) 深度优先(孩子); // 下单 postOrder[ postOrder.length ] = rootNode; 预购: * A B E F C G D 后订购: * E F B G C D A

【讨论】:

这跟今天的xkcd有关系吗? :-P 三种类型。您错过了按顺序遍历。 1 是 Enqueue 根节点,2 是 Dequeue 和输出。那么入队的根节点出队后,队列不会是空的吗?【参考方案7】:

深度优先搜索:

【讨论】:

【参考方案8】:

这是基本的想法:

获取一个新队列 ...用根节点初始化它 ....遍历整个队列并不断从队列中删除一个项目并将其打印出来(或保存等)并检查同一项目是否有任何孩子,如果是这样,将它们推入队列并继续循环,直到您遍历整个段(图)...

【讨论】:

【参考方案9】:

sn-p 有 2 个指针。

void BFS(int v,struct Node **p)

     struct Node *u;

     visited[v-1] = TRUE;
     printf("%d\t",v);
     AddQueue(v);

     while(IsEmpty() == FALSE)
     
         v = DeleteQueue();
         u = *(p+v-1);

         while(u!=NULL)
         
            if(visited(u->data -1) == FALSE)
            
                  AddQueue(u->data);
                  visited[u->data -1]=TRUE;
                  printf("%d\t",u->data);
            

            u = u->next;
         
     

【讨论】:

【参考方案10】:

BFS 和 DFS 适用于各种图。我只为二叉树解释它。 BFS 从上到下,从左到右访问每个节点。例如:

       1
      / \
     7   9
     \  / \
      8 2 3

BFS 给我们:1 7 9 8 2 3. DFS 首先访问每个分支的深度。然后,它回到它的父母身边。你可以遵循这个非正式的规则。首先是左孩子,然后是右孩子,然后是父母。但是,您需要从每个分支的深度开始。例如,这里从 8 开始,因为 7 没有左孩子。然后,您访问父 7。然后,将访问 7 的 1 个父。然后,你去右分支。但是,这次有 2 个作为最左边的孩子。因此,您访问 2(左孩子)然后访问右孩子 3,然后访问他们的父母 9。所以,DFS 给了我们 8 7 1 2 9 3。这是实现:

import java.util.ArrayList;
import java.util.List;

public class TreeTraverse 

    static class Node
        Node(int data)
            this.data = data;
            this.left = null;
            this.right = null;
            this.visited = false;
        
        int data;
        Node left;
        Node right;
        boolean visited;
    

    public static void main(String[] args) 
        //The tree:
        //   1
        //  / \
        // 7   9
        // \  / \
        //  8 2 3

        Node node1 = new Node(1);
        Node node7 = new Node(7);
        Node node9 = new Node(9);
        Node node8 = new Node(8);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        node1.left = node7;
        node1.right = node9;
        node7.right = node8;
        node9.right = node3;
        node9.left = node2;
        System.out.println("DFS: ");
        depthFirstSearch(node1);
        System.out.println("\nBFS: ");
        breadthFirstSearch(node1);

    

    private static void depthFirstSearch(Node node)
        if(node.left == null && node.right == null)
            System.out.print(node.data+" ");
            node.visited = true;
        else if(node.left == null || node.left.visited)
            depthFirstSearch(node.right);
            System.out.print(node.data+" ");
            node.visited = true;
        else
            depthFirstSearch(node.left);
            node.visited = true;
            System.out.print(node.data+" ");
            depthFirstSearch(node.right);

        
    

    private static void breadthFirstSearch(Node node)
        List<Node> al = new ArrayList<>();
        al.add(node);
        while(!al.isEmpty())
            node = al.get(0);
            if(node.left != null)
                int index = al.size();
                al.add(index,node.left);
            
            if(node.right != null)
                int index = al.size();
                al.add(index,node.right);
            
            System.out.print(al.get(0).data+" ");
            al.remove(0);


        
    


我希望它有所帮助。如需克隆项目,请访问:https://github.com/m-vahidalizadeh/foundations/blob/master/src/algorithms/TreeTraverse.java。我希望它有所帮助。

【讨论】:

【参考方案11】:

首先,BFS和DFS是实现二叉树遍历的两种方式。广度优先意味着水平顺序遍历。 Depth First 有 3 种实现方式 -- , , .

预购:

a. Start with root,
b. mark it visited,
c. go to left node
d. (b) - mark it visited
e. Repeat (c) till there is not any new left node remaining
 (We are/might be at leaf node at this point,)
f. Is there any right node available? If yes, go to (a).

级别顺序遍历 时间复杂度 O(n)- 每个节点被访问的次数只有1,意味着总共是n次。

空间复杂性- 最好的情况:树只有左节点,是 O(1) 平均情况:完美二叉树为例,n/2个节点,O(n)

【讨论】:

以上是关于广度优先搜索和深度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章

图的广度、深度优先搜索和拓扑排序

数据结构与算法图遍历算法 ( 深度优先搜索 DFS | 深度优先搜索和广度优先搜索 | 深度优先搜索基本思想 | 深度优先搜索算法步骤 | 深度优先搜索理论示例 )

图的遍历之 深度优先搜索和广度优先搜索

Python算法-深度优先搜索&广度优先搜索(DFS&BFS)

深度优先搜索和广度优先搜索、A星算法三种算法的区别和联系?

深度优先搜索和广度优先搜索、A星算法三种算法的区别和联系?