深入解析BFS算法:C++实现无权图最短路径的高效解决方案

news2025/2/22 10:49:18

        在无权图中,广度优先搜索(BFS)是解决最短路径问题的高效算法。接下来博主从专业角度深入探讨其实现细节,并给出C++代码示例:


目录

一、核心原理

二、算法步骤

三、C++实现关键点

1. 数据结构

2. 边界检查

3. 路径回溯(可选)

四、代码实现

五、路径回溯实现

六、复杂度分析

七、适用场景与限制


一、核心原理

BFS按层遍历节点,确保首次到达目标节点的路径是最短的。其核心特性为:

  • 队列管理:先进先出(FIFO)保证按层扩展。

  • 访问标记:避免重复访问,防止环路。

  • 距离记录:每个节点的距离为父节点距离加1。


二、算法步骤

  1. 初始化:起点入队,标记距离为0。

  2. 遍历队列:逐层处理节点,遍历所有合法邻居。

  3. 终止条件:到达终点时返回距离;队列为空则表示不可达。


三、C++实现关键点

1. 数据结构

  • 队列:存储待处理节点,使用queue<pair<int, int>>

  • 距离矩阵:记录每个节点的最短距离,初始化为-1表示未访问。

  • 方向数组:定义移动方向(如4方向或8方向)。

int dx[] = {-1, 1, 0, 0};  // 上下左右
int dy[] = {0, 0, -1, 1};

2. 边界检查

确保新坐标在网格范围内,且节点可访问(非障碍、未访问)。

3. 路径回溯(可选)

通过父节点矩阵记录路径,回溯时从终点反向追踪至起点。


四、代码实现

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int bfsShortestPath(vector<vector<int>>& grid, pair<int, int> start, pair<int, int> end) {
    int n = grid.size();
    if (n == 0) return -1;
    int m = grid[0].size();
    
    queue<pair<int, int>> q;
    vector<vector<int>> dist(n, vector<int>(m, -1));
    int dx[] = {-1, 1, 0, 0};
    int dy[] = {0, 0, -1, 1};
    
    // 初始化起点
    q.push(start);
    dist[start.first][start.second] = 0;
    
    while (!q.empty()) {
        auto curr = q.front();
        q.pop();
        
        // 到达终点
        if (curr.first == end.first && curr.second == end.second) {
            return dist[curr.first][curr.second];
        }
        
        // 遍历四个方向
        for (int i = 0; i < 4; ++i) {
            int x = curr.first + dx[i];
            int y = curr.second + dy[i];
            
            // 检查新坐标是否合法
            if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == 0 && dist[x][y] == -1) {
                dist[x][y] = dist[curr.first][curr.second] + 1;
                q.push({x, y});
            }
        }
    }
    
    return -1;  // 不可达
}

// 示例用法
int main() {
    vector<vector<int>> grid = {
        {0, 1, 0, 0},
        {0, 0, 0, 1},
        {1, 1, 0, 0},
        {0, 0, 0, 0}
    };
    pair<int, int> start = {0, 0};
    pair<int, int> end = {3, 3};
    
    int shortest = bfsShortestPath(grid, start, end);
    if (shortest != -1) {
        cout << "最短路径长度: " << shortest << endl;
    } else {
        cout << "无法到达终点!" << endl;
    }
    return 0;
}

五、路径回溯实现

扩展代码以记录路径:

vector<pair<int, int>> getPath(vector<vector<pair<int, int>>>& parent, pair<int, int> start, pair<int, int> end) {
    vector<pair<int, int>> path;
    pair<int, int> curr = end;
    while (curr != start) {
        path.push_back(curr);
        curr = parent[curr.first][curr.second];
    }
    path.push_back(start);
    reverse(path.begin(), path.end());
    return path;
}

// 在BFS函数中添加父节点记录
vector<vector<pair<int, int>>> parent(n, vector<pair<int, int>>(m, {-1, -1}));
// ...
if (条件满足) {
    parent[x][y] = curr;
}
// 找到终点后调用getPath

六、复杂度分析

  • 时间复杂度:O(N×M),每个节点处理一次。

  • 空间复杂度:O(N×M),队列和距离矩阵的开销。


七、适用场景与限制

  • 适用:无权图、网格迷宫、社交网络层级关系。

  • 限制:仅处理无权图,带权图需改用Dijkstra或A*算法。

        通过以上实现,BFS能够高效解决无权图中的最短路径问题。正确管理队列和状态标记是保证算法正确性的关键。

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

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

相关文章

LeetCode刷题---二分查找---441

排列硬币 441. 排列硬币 - 力扣&#xff08;LeetCode&#xff09; 题目 你总共有 n 枚硬币&#xff0c;并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯&#xff0c;其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。 给你一个数字 n &#xff0c;计算…

Unity结合Vuforia虚拟按键实现AR机械仿真动画效果

零、最终效果 待上传 一、资源准备 1、Vuforia Vuforia版本不能高于10.17.4&#xff08;往上的版本虚拟按键功能被删除&#xff09; 2、Unity Unity版本必须要高于2022.3.x&#xff0c;不然使用Vuforia插件时会出现bug 二、主要内容 1、添加虚拟按钮 2、为虚拟按钮设置…

网络安全 linux学习计划 linux网络安全精要

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 2.使用命令行 文件系统层次标准&#xff08;FHS&#xff09;是一个文件和目录在Unix和Linux操作系统上面应该如何存储的定义。 /bin 重要的二进制可执行程序/bo…

为AI聊天工具添加一个知识系统 之115 详细设计之56 知识表征 之2

本文要点 要点 知识表征的顶级范畴中最好是先将九个原语primitive T, ⊥, Independent, Relative, Mediating, Physical, Abstract, Continuant,和 Occurrent 进行分组&#xff08;分成2大组 和 4个小组&#xff09;并写出它们的满足公司&#xff0c;然后将它们和三种设计&am…

C#初级教程(1)——C# 与.NET 框架:探索微软平台编程的强大组合

图片来源&#xff1a; https://www.lvhang.site/docs/dotnettimeline 即梦AI - 一站式AI创作平台 一、历史发展脉络 在早期的微软平台编程中&#xff0c;常用的编程语言有 Visual Basic、C、C。到了 20 世纪 90 年代末&#xff0c;Win32 API、MFC&#xff08;Microsoft Found…

Mac m1 连接公司内网

1、创建VPN 1、在系统偏好设置 2、选择网络 3、进行添加 2、添加设置 1、选择VPN 2、类型选择L2TP/IPSec 3、填写服务器IP和账号 4、点击认证设置-填写密码 。然后应用 3、进行特殊配置 网上说苹果系统的问题。 1、创建命令 sudo vim /etc/ppp/options 2、添加内容-主要别…

C++:类与对象,定义类和构造函数

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std; //如何让定义一个类 // 封装 // 1、将数据和方法定义到一起。 // 2、把想给你看的数据给你看&#xff0c;不想给你看的封装起来。 通过访问限定符来实现 class Stack { public: //1.成…

Nginx环境安装

一、官网地址 Nginx官网&#xff1a;http://nginx.org/ Nginx中文网&#xff1a;https://nginx.p2hp.com/ 二、Nginx版本 mainline version 开发版本stableversion 稳定版本legacy version 历史版本 三、Windows系统安装Nginx 第一步&#xff1a;选择Windows版本&#xff0c;…

Spring AI + Ollama 实现调用DeepSeek-R1模型API

一、前言 随着人工智能技术的飞速发展&#xff0c;大语言模型&#xff08;LLM&#xff09;在各个领域的应用越来越广泛。DeepSeek 作为一款备受瞩目的国产大语言模型&#xff0c;凭借其强大的自然语言处理能力和丰富的知识储备&#xff0c;迅速成为业界关注的焦点。无论是文本生…

android系统SystemServer进程启动流程分析

目录 一,SystemServer整体框架 二,SystemServer启动源码分析 2.1,重要的概念 2.2,启动入口 2.3,创建对应进程的binder 三,binder驱动和binder线程池 四,SystemServer真正启动方法 4.1 SystemServer main方法里面主要做了几件事情 1)创建SystemServiceManager管理所有的…

Oracle 深入理解Lock和Latch ,解析访问数据块全流程

Oracle 锁机制介绍 根据保护对象的不同&#xff0c;单实例Oracle数据库锁可以分为以下几大类&#xff1a; DML lock&#xff08;data locks&#xff0c;数据锁&#xff09;&#xff1a;用于保护数据的完整性&#xff1b; DDL lock&#xff08;dictionary locks&#xff0c;字典…

如何基于transformers库通过训练Qwen/DeepSeek模型的传统分类能力实现文本分类任务

文章目录 模型与环境准备文档分析源码解读模型训练及推理方式进阶:CPU与显存的切换进阶:多卡数据并行训练🔑 DDP 训练过程核心步骤🚫 DDP 不适用于模型并行⚖️ DDP vs. Model Parallelism⚙️ 解决大模型训练的推荐方法🎉进入大模型应用与实战专栏 | 🚀查看更多专栏…

Unity中一个节点实现植物动态(Shader)

1 . 核心思路就操作顶点作往复运动&#xff1b; 核心代码&#xff1a; half stage1 dot(positionOS, float3(0, 1, 0)) * _Strength; half stage2 sin(dot(positionOS, float3(1, 0, 0)) * _Strength _Time.y * _Speed); half stage3 stage1 * stage2 * float3(0.001,…

PrimeTime:工具简介

相关阅读 PrimeTimehttps://blog.csdn.net/weixin_45791458/category_12900271.html?spm1001.2014.3001.5482 PrimeTime是PrimeTime Suite中的一个工具&#xff0c;能够执行全芯片级、门级的静态时序分析&#xff0c;这是芯片设计和分析流程中的一个关键部分。该工具通过检查…

【拜读】Tensor Product Attention Is All You Need姚期智团队开源兼容RoPE位置编码

姚期智团队开源新型注意力&#xff1a;张量积注意力&#xff08;Tensor Product Attention&#xff0c;TPA&#xff09;。有点像一种「动态的LoRA」&#xff0c;核心思路在于利用张量分解来压缩注意力机制中的 Q、K、V 表示&#xff0c;同时保留上下文信息&#xff0c;减少内存…

Docker-技术架构演进之路

目录 一、概述 常见概念 二、架构演进 1.单机架构 2.应用数据分离架构 3.应用服务集群架构 4.读写分离 / 主从分离架构 5.引入缓存 —— 冷热分离架构 6.垂直分库 7.业务拆分 —— 微服务 8.容器化引入——容器编排架构 三、尾声 一、概述 在进行技术学习过程中&am…

用Chrome Recorder轻松完成自动化测试脚本录制

前言 入门自动化测试,录制回放通常是小白测试首先用到的功能。而录制回放工具也一直是各大Web自动化测试必然会着重提供的一块功能。 早期WinRunner、QTP这样的工具,自动化测试可以说是围绕录制回放开展的。近年像Selenium也提供有录制工具 Selenium IDE,Playwright也包含…

python中的异常-模块-包

文章目录 异常异常的定义异常捕获语法捕获常规异常捕获指定异常捕获多个异常捕获所有异常异常else异常finally 异常传递总结 模块概念导入自定义模块及导入main方法all变量 总结 包自定义包定义pycharm中建包的基本步骤导入方式 第三方包 异常 异常的定义 当检测到一个错误时…

【GPU驱动】OpenGLES图形管线渲染机制

OpenGLES图形管线渲染机制 OpenGL/ES 的渲染管线也是一个典型的图形流水线&#xff08;Graphics Pipeline&#xff09;&#xff0c;包括多个阶段&#xff0c;每个阶段都负责对图形数据进行处理。管线的核心目标是将图形数据转换为最终的图像&#xff0c;这些图像可以显示在屏幕…

ssm-day06 ssm整合

从springMVC总结再回顾一下 60节 整合就是应用框架&#xff0c;并且把这个框架放到IOC容器中 web容器&#xff1a;装springMVC和controller相关的web组件 root容器&#xff1a;装业务和持久层相关的组件 子容器可以引用父容器中的组件&#xff0c;父容器不能调子容器 一个容器…