首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

如何通透理解:BFS和DFS优先搜索算法(23年修订版)

  • 25-03-02 15:42
  • 4122
  • 12468
blog.csdn.net

前言

本文最早写于二零一一年一月一日,十余年过去,如今再看,之前写的确实一言难尽(包括评论区也有不少朋友指出文章质量、文章排版都有待提高),故重写本文

第一部分 什么是BFS与DFS

1.1 什么是BFS

BFS(广度优先搜索)是一种图遍历算法,它从一个起始点开始,逐层扩展搜索范围,直到找到目标节点为止。

这种算法通常用于解决“最短路径”问题,比如在迷宫中找到从起点到终点的最短路径

  1. 首先,你会从起点开始,检查所有与它相邻的位置,也就是距离起点为1的位置
  2. 然后,你会继续向外扩展,检查所有距离起点为2的位置,以此类推,直到找到出口

在BFS中,你可以使用队列来存储待搜索的节点。起始点首先加入队列中,然后不断从队列中取出节点,检查它是否是目标节点。如果不是,就将它的所有未被访问过的邻居加入队列中。这样,队列中的节点总是按照它们距离起点的距离排序,先加入队列的节点总是先被取出来搜索。

通过这种方式,BFS可以找到起点到目标节点的最短路径。在实际应用中,BFS还可以用于拓扑排序、连通性检测等问题的解决。

1.2 什么是DFS

DFS(深度优先搜索)是一种图遍历算法,它从一个起始点开始,一直往下走直到不能再走为止,然后返回到前一个节点,继续探索它的其他分支,直到找到目标节点为止。这种算法通常用于解决“遍历”问题,比如在树中查找所有的叶子节点。

要理解DFS,也还可以想象自己在迷宫中寻找所有可行的路径

  1. 首先,你会从起点开始,顺着一条路一直走,直到你走到一个死胡同
  2. 再返回到前一个节点,继续探索其他分支

在探索过程中,你可以使用栈来存储已经访问过的节点,以便后续回溯。

在DFS中,你可以使用递归或栈来实现深度优先搜索。通过这种方式,DFS可以找到所有可行的路径,或者在树中查找所有的叶子节点。

在实际应用中,DFS还可以用于拓扑排序、连通性检测等问题的解决。与BFS相比,DFS通常更适合处理深度优先的问题,而BFS更适合处理广度优先的问题。

1.3 BFS与DFS的比较

 如果分别用DFS 与 BFS 将二叉树的所有结点遍历一遍,那么它们遍历结点的顺序分别如下所示

接下来,让我们先看看在二叉树上进行 BFS 遍历和 DFS 遍历的代码比较

首先是DFS 遍历使用递归(递归的方式隐含地使用了系统的栈):

  1. void dfs(TreeNode* root)
  2. {
  3. if (root == nullptr)
  4. {
  5. return;
  6. }
  7. // 依次递归遍历它的左子树和右子树
  8. dfs(root->left);
  9. dfs(root->right);
  10. }

其次,BFS 遍历使用队列数据结构:

  1. void bfs(TreeNode* root)
  2. {
  3. // 创建一个队列
  4. queue q;
  5. q.push(root);
  6. while (!q.empty())
  7. {
  8. // 在每次循环中,使用 q.front() 获取队头节点,并将其出队
  9. TreeNode* node = q.front();
  10. q.pop();
  11. // 检查这个节点的左右子节点是否为空,如果不为空,就将它们加入队列中
  12. if (node->left != nullptr)
  13. {
  14. q.push(node->left);
  15. }
  16. if (node->right != nullptr)
  17. {
  18. q.push(node->right);
  19. }
  20. }
  21. }

第二部分 应用BFS求解的典型问题:层序遍历

例题:二叉树的层序遍历

给定一个二叉树,返回其按层序遍历得到的节点值。 层序遍历即逐层地、从左到右访问所有结点。

什么是层序遍历呢?简单来说,层序遍历就是把二叉树分层,然后每一层从左到右遍历 (配图来源):

乍一看,这个遍历顺序和 BFS 是一样的,我们可以直接用 BFS 得出层序遍历结果。然而,层序遍历要求的输入结果和 BFS 是不同的。层序遍历要求我们区分每一层,也就是返回一个二维数组。而 BFS 的遍历结果是一个一维数组,无法区分每一层。

 那么,怎么给 BFS 遍历的结果分层呢?我们首先来观察一下 BFS 遍历的过程中,结点进队列和出队列的过程:

 截取 BFS 遍历过程中的某个时刻:

可以看到,此时队列中的结点是 3、4、5,分别来自第 1 层和第 2 层。这个时候,第 1 层的结点还没出完,第 2 层的结点就进来了,而且两层的结点在队列中紧挨在一起,我们 无法区分队列中的结点来自哪一层。

因此,我们需要稍微修改一下代码,在每一层遍历开始前,先记录队列中的结点数量n(也就是这一层的结点数量),然后一口气处理完这一层的n个结点。

  1. // 二叉树的层序遍历
  2. void bfs(TreeNode* root)
  3. {
  4. queue q;
  5. q.push(root);
  6. while (!q.empty())
  7. {
  8. int n = q.size();
  9. for (int i = 0; i < n; i++)
  10. {
  11. TreeNode* node = q.front();
  12. q.pop();
  13. if (node->left != nullptr)
  14. {
  15. q.push(node->left);
  16. }
  17. if (node->right != nullptr)
  18. {
  19. q.push(node->right);
  20. }
  21. }
  22. }
  23. }

这样,我们就将 BFS 遍历改造成了层序遍历。在遍历的过程中,结点进队列和出队列的过程为:

可以看到,在 while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列,这样就实现了层序遍历。

最终我们得到的题解代码为:

  1. vectorint>> levelOrder(TreeNode* root)
  2. {
  3. vectorint>> res;
  4. queue q;
  5. if (root != nullptr)
  6. {
  7. q.push(root);
  8. }
  9. while (!q.empty())
  10. {
  11. int n = q.size();
  12. vector<int> level;
  13. for (int i = 0; i < n; i++)
  14. {
  15. TreeNode* node = q.front();
  16. q.pop();
  17. level.push_back(node->val);
  18. if (node->left != nullptr)
  19. {
  20. q.push(node->left);
  21. }
  22. if (node->right != nullptr)
  23. {
  24. q.push(node->right);
  25. }
  26. }
  27. res.push_back(level);
  28. }
  29. return res;
  30. }

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览49577 人正在系统学习中
注:本文转载自blog.csdn.net的v_JULY_v的文章"http://blog.csdn.net/v_JULY_v/archive/2011/01/01/6111353.aspx"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top