【数据结构】广度优先遍历(BFS)模板及其讲解

🎊专栏【数据结构】

🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。

🎆音乐分享【勋章】

大一同学小吉,欢迎并且感谢大家指出我的问题🥰

目录

🎁定义

🎁遍历方法 

🎁根据题目来理解BFS

🏳️‍🌈走迷宫

🏳️‍🌈思路

🏳️‍🌈代码(BFS模板)

🏳️‍🌈分析


🎁定义

        BFS 全称是 Breadth-First-Search,即广度优先搜索。它是一种图遍历算法,在搜索时先访问起始顶点的所有邻居顶点,然后再依次访问这些邻居顶点的邻居顶点,直到遍历完整个图。这种算法可以用来寻找两个节点之间的最短路径,也可以用于树的遍历等其他场景。

        BFS 通常使用队列来实现,从起始顶点开始,将其加入队列中,然后访问它的邻居顶点,并将其加入队列尾部。接着将队列头部的顶点出队并访问其邻居顶点,将未访问的邻居顶点加入队列中,直到队列为空为止。

        BFS 算法在运行时,由于是逐层遍历,因此每一层的节点都会被访问,遍历到的第一个目标节点所在的层数也就是最短距离,因此 BFS 算法可以用来求解无权图的最短路径问题。

🎁遍历方法 

如下图所示

由于是逐层遍历,那么遍历顺序是 1 -> 2 -> 3 -> 4 -> 5 - > 6 -> 7 - > 8

🎁根据题目来理解BFS

🏳️‍🌈走迷宫

给定一个n*m的二维整数数组,用来表示一个迷宫,数组中只包含0或1,其中0表示可以走的路,1表示不可通过的墙壁。

最初,有一个人位于左上角(1, 1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。

请问,该人从左上角移动至右下角(n, m)处,至少需要移动多少次。

数据保证(1, 1)处和(n, m)处的数字为0,且一定至少存在一条通路。

输入格式

第一行包含两个整数n和m。

接下来n行,每行包含m个整数(0或1),表示完整的二维数组迷宫。

输出格式

输出一个整数,表示从左上角移动至右下角的最少移动次数。

数据范围

1≤n,m≤100


输入样例:
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例:
8

🏳️‍🌈思路

        从起点开始,往前走第一步,记录下所有第一步能走到的点,然后从所第一步能走到的点开始,往前走第二步,记录下所有第二步能走到的点,重复下去,直到走到终点。输出步数即可。

🏳️‍🌈代码(BFS模板)

#include <cstring>   // 处理内存块的头文件
#include <iostream>  // 标准输入输出头文件
#include <algorithm> // STL 常用算法头文件
#include <queue>     // 队列头文件

using namespace std;  // 命名空间

typedef pair<int, int> PII;  // 定义 pair 类型

const int N = 110;  // 设定二维数组的大小

int n, m;           // n 和 m 分别代表二维数组的行和列
int g[N][N], d[N][N];  // g 表示从输入中读取的二维数组信息,d 用来记录遍历每个点的距离

int bfs()  // BFS 算法主函数
{
    queue<PII> q;  // 定义一个队列,队列中的元素是 pair 类型的变量

    memset(d, -1, sizeof d);  // 初始化距离数组 d 数组的值都设置为 -1,表示还未遍历到
    d[0][0] = 0;  // 起点格子的距离设置为 0
    q.push({0, 0});  // 将起点的坐标加入队列中

    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};  // 定义上右下左四个方向的移动距离

    while (q.size())  // 队列不为空
    {
        auto t = q.front();  // 取出队首元素,并标记当前这个点已经访问过了
        q.pop();

        for (int i = 0; i < 4; i ++ )  // 尝试四个方向的移动
        {
            int x = t.first + dx[i], y = t.second + dy[i];  // 计算出移动后的点的坐标

            if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)  // 如果移动后的点满足条件(没有越界、不是障碍、且未遍历到)
            {
                d[x][y] = d[t.first][t.second] + 1;  // 更新移动后的点的距离
                q.push({x, y});  // 将新的点加入队列
            }
        }
    }

    return d[n - 1][m - 1];  // 返回终点的距离,即最短路径长度
}

int main()  // 主函数
{
    cin >> n >> m;  // 读入二位数组的行和列数
    for (int i = 0; i < n; i ++ )  // 读入二维数组的每一个元素
        for (int j = 0; j < m; j ++ )
            cin >> g[i][j];

    cout << bfs() << endl;  // 调用 BFS 算法函数,输出最少需要多少步才能从起点走到终点

    return 0;  // 返回运行成功标志
}

🏳️‍🌈分析

~用 g 存储地图,f存储起点到其他各个点的距离。
~从起点开始广度优先遍历地图。
~当地图遍历完,就求出了起点到各个点的距离,输出d[n][m]即可。


 while (q.size())  // 队列不为空
 {
        auto t = q.front();  // 取出队首元素,并标记当前这个点已经访问过了
        q.pop();

        for (int i = 0; i < 4; i ++ )  // 尝试四个方向的移动
        {
            int x = t.first + dx[i], y = t.second + dy[i];  // 计算出移动后的点的坐标

            if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)  // 如果移动后的点满足条件(没有越界、不是障碍、且未遍历到)
            {
                d[x][y] = d[t.first][t.second] + 1;  // 更新移动后的点的距离
                q.push({x, y});  // 将新的点加入队列
            }
        }
    }

上面这一段代码就是来寻找下一步要走的路,尝试四个方向的移动,int x = t.first + dx[i], y = t.second + dy[i];  计算出移动后的点的坐标,判断4个方向是否满足移动条件【if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)  没有越界、不是障碍、且未遍历到)】,如果找到了,就 d[x][y] = d[t.first][t.second] + 1;更新移动后的点的距离(距离+1),并且 q.push({x, y});   将新的点加入队列,标记这一点,表示这个点已经访问过了

🥰如果大家有不明白的地方,或者文章有问题,欢迎大家在评论区讨论,指正🥰   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/21530.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是边缘计算盒子?边缘计算盒子可以做什么?一文带你了解边缘计算云服务器 ECS

上文&#xff0c;我们已经为大家介绍了什么是边缘计算、边缘计算的诞生、以及边缘计算与CDN之间的关系&#xff0c;感兴趣的小伙伴欢迎阅读以往文章&#xff1a; 边缘计算节点是啥&#xff1f;边缘计算与CDN有什么关系&#xff1f;一文带你了解边缘计算节点BEC&#xff08;1&am…

nest笔记十一:一个完整的nestjs示例工程(nestjs_template)

概述 链接&#xff1a;nestjs_template 相关文章列表 nestjs系列笔记 示例工程说明 这个工程是我使用nestjs多个项目后&#xff0c;总结出来的模板。这是一个完整的工程&#xff0c;使用了yaml做为配置&#xff0c;使用了log4js和redis和typeorm&#xff0c;sawgger&#…

Elasticsearch 集群部署插件管理及副本分片概念介绍

Elasticsearch 集群配置版本均为8以上 安装前准备 CPU 2C 内存4G或更多 操作系统: Ubuntu20.04,Ubuntu18.04,Rocky8.X,Centos 7.X 操作系统盘50G 主机名设置规则为nodeX.qingtong.org 生产环境建议准备单独的数据磁盘主机名 #各自服务器配置自己的主机名 hostnamectl set-ho…

STM32实现基于RS485的简单的Modbus协议

背景 我这里用STM32实现&#xff0c;其实可以搬移到其他MCU&#xff0c;之前有项目使用STM32实现Modbus协议 这个场景比较正常&#xff0c;很多时候都能碰到 这里主要是Modbus和变频器通信 最常见的是使用Modbus实现传感器数据的采集&#xff0c;我记得之前用过一些传感器都…

学习RHCSA的day.03

目录 2.6 Linux系统的目录结构 2.7 目录操作命令 2.8 文件操作命令 2.6 Linux系统的目录结构 1、Linux目录结构的特点 分区加载于目录结构&#xff1a; 使用树形目录结构来组织和管理文件。整个系统只有一个位于根分区的一个根目录&#xff08;树根&#xff09;、一棵树。…

盘点 | 10大类企业管理系统有哪些

人类的发展史也是一部工具的进化史&#xff0c;企业管理手段同样不例外。移动互联网时代给了传统低下的手工操作方式致命一击&#xff0c;应运而生的各类企业管理系统工具为企业管理插上腾飞的翅膀&#xff0c;彻底颠覆了手动低效率的历史&#xff0c;变得更加移动化、智能化。…

求最小生成树(Prim算法与Kruskal算法与并查集)

目录 1、案例要求2、算法设计与实现2.1 Prim算法2.1.1 构造无向图2.1.2 编写Prim算法函数2.1.3 实现代码2.1.4 运行结果截图 2.2 Kruskal算法2.2.1 构造无向图2.2.2 编写并查集UnionFind类2.2.3 编写Kruskal算法2.2.4 实现代码2.2.5 运行结果截图 3、总结 1、案例要求 利用贪心…

低代码与其拓荒,不如颠覆开发行业

目录 一、前言 二、低代码是一个值得信赖的“黑盒子” 粗略总结&#xff0c;开发者对低代码平台所见即所得设计器有两种反应&#xff1a; 三、人人都爱黑盒子 四、用“低代码平台”来开发是什么样的感受&#xff1f; 五、结论 一、前言 在科幻电影中&#xff0c;我们看到…

【OpenCV】C++红绿灯轮廓识别+ROS话题实现

目录 前言 一、背景知识 Opencv轮廓检测 ROS相关知识 二、环境依赖 三、具体实现 Step1&#xff1a;初始化ROS&#xff0c;订阅话题 Step2&#xff1a;接收话题&#xff0c;进入回调 1. 帧处理 2. 膨胀腐蚀处理 Step3&#xff1a;红绿特征处理 1. 提取绘制轮廓 2…

【网络协议详解】——数据链路层协议(学习笔记)

&#x1f4d6; 前言&#xff1a;数据链路层是 OSI 模型中的第二层&#xff0c;位于物理层之上&#xff0c;是通信网络中的重要组成部分之一。数据链路层协议负责将网络层传输的数据分组封装成帧&#xff0c;传输到物理层&#xff0c;并通过物理介质进行传输。同时&#xff0c;数…

算法笔记:A2-A4-RSRQ切换算法

1 LTE 切换 LTE切换是移动通信网络中的一个过程&#xff0c;移动设备在保持无间断服务的情况下&#xff0c;将其连接从一个基站切换到另一个基站。当移动设备离开当前基站的覆盖范围或网络资源拥塞时&#xff0c;就需要进行切换。LTE切换通常是基于特定的条件触发的&#xff0…

makefile 学习(1):C/C++ 编译过程

1. GCC 介绍 1.1 介绍 GCC 官方文档 https://gcc.gnu.org/onlinedocs/ 官方文档是最权威的&#xff0c;网上所有的答案都来自官方文档国内论坛参差不齐&#xff0c;找到好的答案比较花时间&#xff0c;并且很容易被错误的文档误导。所以推荐看官方文档靠谱点&#xff0c;并且…

二、数据字典开发

文章目录 二、数据字典开发1、搭建service-cmn模块1.1 搭建service-cmn模块1.2 修改配置1.3 启动类 2、数据字典列表2.1 数据字典列表接口2.1.1 model模块添加数据字典实体2.1.2 添加数据字典mapper2.1.4 添加数据字典controller 2.2 数据字典列表前端2.2.1 添加路由2.2.2 定义…

【Java算法题】剑指offer_01数据结构

前言 刷题链接&#xff1a; https://www.nowcoder.com/exam/oj/ta?page2&tpId13&type265 1. 链表 JZ24 反转链表 思路&#xff1a;基本操作&#xff0c;如下所示。 /* public class ListNode {int val;ListNode next null;ListNode(int val) {this.val val;} }…

ad18学习笔记一

如何自学altium designer如何自学altium designer&#xff1f; - 知乎如何自学altium designer 这里面有ad官方推荐的b站的视频&#xff1a;可以直接去b站关注ad官方账号 AltiumChina&#xff0c;它本身就发布了很多实用教程。 在知乎的这个界面也有Altium Designer Ver18_官…

c++ 11标准模板(STL) std::set(六)

定义于头文件 <set> template< class Key, class Compare std::less<Key>, class Allocator std::allocator<Key> > class set;(1)namespace pmr { template <class Key, class Compare std::less<Key>> using se…

如何使用SCQA模型提高表达能力

SCQA架构是“结构化表达”工具。 一、什么是“SCQA架构”&#xff1f;‍ S&#xff08;Situation&#xff09;情景——由熟悉的情境或事实引入 C&#xff08;Complication&#xff09;冲突——指出实际面临的困境或冲突 Q&#xff08;Question&#xff09;疑问——你如何分析…

文本三剑客正则表达式3

文章目录 文本三剑客&正则表达式31 awk工作原理2 awk的基本格式及其内置变量2.1 基本格式2.2 内置变量2.3 示例2.3.1 直接打印所有内容2.3.2 取每一行的第一列2.3.3 打印行号&#xff0c;及所有内容2.3.4 打印第三行2.3.5 打印2-4行2.3.6 打印第2行和第4行2.3.7 用正则表达…

基于harbor安装私有镜像仓库

目录 Harbor介绍 Harbor安装 下载完成后&#xff0c;在压缩包解压到/usr/local目录下&#xff1a; 修改Harbor配置文件 推送本地镜像到harbor上 1、给本地镜像打一个标签 2、 设置docker的daemon.json 3、重启docker 4、使用docker登录harbor 5、把本地的镜像push到harbor…

银豆信息张雪灿:钻石级合作伙伴的增长秘诀

编者按&#xff1a; 杭州银豆信息技术有限公司&#xff08;简称“银豆”&#xff09;&#xff0c;是一家专注于云计算服务的高科技企业&#xff0c;目前已为2000家企业级客户提供了专业的行业解决方案, 与人民网、光大银行、长安汽车金融、vivo金融、浙江省农科院、淄博市大数…