• DFS 深度优先搜索 —— 一种探险的算法


    一、引言

    深度优先搜索是什么?

    深度优先搜索(DFS, Depth First Search)是一个针对图和树的遍历算法。

    DFS与其他搜索算法的区别。

    1. 深度优先搜索(DFS)是一种利用递归实现的搜索算法。在搜索过程中,DFS从根节点开始,探索尽可能深的分支,如果当前节点没有未访问的邻接点,则回溯到上一个节点,继续探索下一个未访问的邻接点。DFS使用的数据结构是栈,其特点是一旦放入栈中,就不会被移除,直到栈顶被压入新的元素或者栈被清空。因此,DFS是沿着树或图的深度遍历,直到找到目标或达到无法继续搜索为止。
    2. 广度优先搜索(BFS)则是一种利用队列实现的搜索算法。其搜索过程和“湖面丢进一块石头激起层层涟漪”类似,先搜索邻居,搜完邻居再搜邻居的邻居。具体来说,BFS将当前节点的所有未访问的邻接点放入队列中,然后从队列的前端取出节点进行访问,同时将该节点标记为已访问。这个过程会一直进行,直到队列为空,即没有未访问的邻接点。由于BFS按照广度进行搜索,因此它更适用于广度较大的图或树。

    DFS在各种计算问题中的应用。

    DFS和BFS都是用于遍历或搜索树或图的算法,但它们适用于不同的场景。

    1. DFS(深度优先搜索)的主要应用场景包括:
    • 迷宫搜索:如果要在给定的迷宫中找到从起点到终点的路径,DFS是一个合适的选择,因为它可以深入地搜索路径,直到找到出口或无法继续前进。
    • 回溯算法:对于解决某些需要回溯的问题,如求解数独或解决逻辑推理问题,DFS是一种常用的算法,因为它可以深入地搜索问题的解空间,直到找到解决方案或确定无解。
    • 图的遍历:如果需要遍历一个图的所有节点,DFS可以高效地实现这个目标,因为它可以深入地搜索图的分支,直到找到所有未访问的节点。
    1. BFS(广度优先搜索)的主要应用场景包括:
    • 最短路径问题:BFS可以用于寻找从一个节点到另一个节点的最短路径,因为它会先遍历离起点近的节点,再逐步向外扩展,直到找到目标节点。例如,在解决图中的最短路径问题时,BFS通常是一个合适的选择。
    • 图的遍历:如果需要按层次遍历一个图,BFS是一个很好的选择。它会先访问离起点最近的节点,然后逐层向外扩展,直到访问完所有的节点。
    • 宽度优先搜索:在一些需要将信息分批处理的场景中,如网络爬虫的页面抓取,BFS按广度进行搜索和处理,能够高效地处理大量信息。

    需要注意的是,DFS和BFS在具体应用中可能受到一些限制。例如,DFS不适合用于循环图或存在多个起点的图,因为它可能会陷入无限循环;而BFS也不适合用于稀疏图或非常大的图,因为它需要存储大量的节点和边信息。因此,在实际应用中需要根据具体的问题和数据结构选择合适的搜索算法。

    二、深度优先搜索的基本概念

    定义和术语

    1. 搜索树:在深度优先搜索中,每个节点的搜索顺序都会被记录下来,这些顺序形成一个树形结构,被称为搜索树。
    2. 根节点:搜索树的第一个节点被称为根节点,它是搜索的起点。
    3. 叶节点:搜索树的最后一个节点被称为叶节点,它是搜索的终点。
    4. 节点扩展:在深度优先搜索中,从一个节点开始,通过扩展该节点的所有未访问过的邻接节点,来寻找新的解。
    5. 回溯:当深度优先搜索无法通过当前节点的邻接节点找到新的解时,会回溯到上一个节点,并尝试其他未访问过的邻接节点。
    6. 剪枝:在深度优先搜索中,可以通过对搜索树进行剪枝来减少搜索的空间,从而提高搜索效率。剪枝是通过判断当前分支不可能存在解而将其删除。
    7. 记忆化搜索:在深度优先搜索中,可以使用记忆化搜索来避免重复搜索已经访问过的节点。记忆化搜索是一种将已访问过的节点存储起来,以便在后续搜索中可以快速查找的方法。

     

    DFS的搜索过程

    深度优先搜索(DFS)(C++) - 知乎

    终止条件和回溯

            终止条件

    1. 遍历完所有的顶点:DFS是一种深度优先的搜索算法,它会遍历图中的所有顶点。当所有的顶点都被访问过,也就是没有未遍历的节点时,搜索过程就会终止。

    2. 找到目标:如果DFS的目标是找到特定的顶点或路径,当找到这个目标时,搜索过程就会终止。

    3. 达到终止状态:在某些情况下,图中的顶点可能满足某种终止状态。例如,对于一个排程问题,如果所有的任务都已经完成或者无法再被调度,搜索过程就会终止。

    4. 没有更多的未访问顶点:如果DFS中没有更多的未访问顶点,也就是说所有的顶点都已被访问过,此时搜索过程就会终止。

            回溯与DFS的关系

            DFS 是一个劲的往某一个方向搜索,而回溯算法是建立在 DFS 基础之上的,但不同的是在搜索过程中,达到结束条件后,恢复状态,回溯上一层,再次搜索。因此回溯算法与 DFS 的区别就是有无状态重置

     

    三、深度优先搜索的实现

    • 递归实现。
      ​​​​​​​

      1. function dfs($graph, $start, $visited = [])
      2. {
      3. // 标记当前节点为已访问
      4. $visited[$start] = true;
      5. echo $start . " ";
      6. // 遍历当前节点的所有邻居节点
      7. foreach ($graph[$start] as $neighbor) {
      8. // 如果邻居节点未被访问,则递归调用 dfs 函数
      9. if (empty($visited[$neighbor])) {
      10. dfs($graph, $neighbor, $visited);
      11. }
      12. }
      13. }
      14. // 示例图的邻接表表示
      15. $graph = [
      16. 0 => [1, 2],
      17. 1 => [2],
      18. 2 => [0, 3],
      19. 3 => [3]
      20. ];
      21. // 从节点 2 开始进行深度优先搜索
      22. dfs($graph, 2);

    • 非递归实现。

      • 用栈实现

    1. function dfs($graph, $start)
    2. {
    3. $visited = [];
    4. $stack = [];
    5. $stack[] = $start;
    6. while (!empty($stack)) {
    7. $node = array_pop($stack);
    8. // 标记当前节点为已访问
    9. $visited[$node] = true;
    10. echo $node . " ";
    11. // 将当前节点的未访问邻居节点入栈
    12. foreach ($graph[$node] as $neighbor) {
    13. if (empty($visited[$neighbor])) {
    14. $stack[] = $neighbor;
    15. }
    16. }
    17. }
    18. }
    19. // 示例图的邻接表表示
    20. $graph = [
    21. 0 => [1, 2],
    22. 1 => [2],
    23. 2 => [0, 3],
    24. 3 => [3]
    25. ];
    26. // 从节点 2 开始进行深度优先搜索
    27. dfs($graph, 2);

     

    四、深度优先搜索的优化

    1. 记忆化搜索。

    2. 使用启发式信息。

    3. 处理重复节点。

    五、深度优先搜索的应用实例

    1. 图的遍历。

    2. 树的遍历

    3. 八皇后问题。

    4. 数独。

    六、总结与展望
    ​​​​​​​

    深度优先搜索(DFS)是一种常用的图遍历算法,它具有以下优点:

    1. DFS能够遍历整张图,包括所有分支和节点,不会出现遗漏或未访问的节点。
    2. 在一些情况下,DFS的算法复杂度比其他遍历算法更低,因此在某些情况下更适合大规模的图。
    3. 在某些情况下,DFS需要使用递归或栈来实现,这可能会导致大量的内存开销和递归调用开销。
    4. 如果图中存在大量的节点和边,可能会导致搜索效率低下,需要更复杂的优化策略来提高效率。
    5. DFS对于图的某些特性(例如连通性、无环性等)没有很好的处理方式,需要额外的算法来处理。
    6. 在分布式系统中,DFS的局限性更加明显。例如,DFS在分布式环境中需要实现节点间的通信和同步,这可能会增加系统的开销和复杂性。

    场景总结

    1. 搜索引擎:DFS被广泛应用于网页信息的抓取和索引,是搜索引擎的重要组成部分。通过DFS遍历整个网页,可以获得网页之间的链接关系,以及网页的内容和元数据等信息,为搜索引擎提供索引和搜索结果。

    2. 图数据库:图数据库是一种以图形结构为基础的数据库,可以存储、管理和查询实体之间的复杂关系。DFS是图数据库中一种非常有用的查询算法,可以高效地遍历和查询图中的节点和边。

    3. 网络安全:DFS在网络安全领域也有很多应用,例如攻击面扫描、漏洞扫描、入侵检测等。通过DFS遍历整个网络,可以发现网络中的漏洞和弱点,及时进行修补和防范。

    4. 数据挖掘:DFS在数据挖掘领域中也有很多应用,例如关联规则挖掘、聚类分析、序列模式挖掘等。通过DFS遍历数据集中的所有元素,可以发现数据之间的关联和规律,为决策提供有力的支持。

    5. 人工智能:DFS在人工智能领域中也有很多应用,例如知识图谱、自然语言处理、机器学习等。通过DFS遍历知识图谱中的节点和边,可以进行知识的表示、推理和学习。

  • 相关阅读:
    【软件测试】初识测试
    Redis笔记基础篇:6分钟看完Redis的八种数据类型
    leetcode-剑指 Offer II 001. 整数除法
    在Linux中tomcat占用内存过高可以通过导出hprof日志来解决
    JDY-16 蓝牙4.2模块串口测试方法
    人类真的与恐龙无缘见面吗?看看雕刻和绘画怎样说
    你真的了解 Session 和 Cookie 吗?
    数据结构之<二叉搜索树>
    JVM 引用的分类
    Cairo
  • 原文地址:https://blog.csdn.net/m0_37962554/article/details/133171048