【C++】深入浅出“图”——最短路径算法

【C++】深入浅出“图”——最短路径算法

文章目录

一、Dijkstra算法

最短路径问题是指,从在带权的有向图中从某一顶点出发,找到通往另一顶点的最短路径,“最短”指的是沿路径各边的权值总和最小。

Dijkstra算法是单源最短路径的经典贪心算法,只能用于没有负权的图。它从起点出发,每次选当前距离最小且未确定最短路径的节点,用它去松弛(更新)所有邻接点的最短路径估计值,标记该节点为 “已确定”,重复此过程直到所有节点处理完毕,最终得到起点到图中所有节点的最短路径。

在这里插入图片描述
// src是选定的起点,dist记录起点到各点的最短路径,pPath记录到每个点的最短路径的前驱顶点下标voidDijkstra(const V& src, vector<W>& dist, vector<int>& pPath){ size_t srci =GetVertexIndex(src); size_t n = _vertexs.size(); dist.resize(n, MAX_W); pPath.resize(n,-1); dist[srci]=0; pPath[srci]= srci;// 已经确定最短路径的顶点集合 vector<bool>S(n,false);for(size_t j =0; j < n;++j){// 选最短路径顶点且不在S更新其他路径int u =0; W min = MAX_W;for(size_t i =0; i < n;++i){if(S[i]==false&& dist[i]< min){ u = i; min = dist[i];}} S[u]=true;// 松弛更新u连接顶点v srci->u + u->v < srci->v 更新for(size_t v =0; v < n;++v){if(S[v]==false&& _matrix[u][v]!= MAX_W && dist[u]+ _matrix[u][v]< dist[v]){ dist[v]= dist[u]+ _matrix[u][v]; pPath[v]= u;}}}}

二、Bellman_Ford算法

Bellman_Ford算法能用来解决负权图的单源最短路径问题,但是它的时间复杂度高于Dijkstra算法,本质是暴力求解。从起点出发,把图里所有边从头到尾松弛一遍,重复n次,就能算出起点到所有点的最短路径;因为任何最短路径最多只经过n‑1条边。跑完之后再扫一遍所有边,如果还能更新距离,就说明图里有负权回路,最短路径不存在。

在这里插入图片描述
boolBellmanFord(const V& src, vector<W>& dist, vector<int>& pPath){ size_t n = _vertexs.size(); size_t srci =GetVertexIndex(src);// vector<W> dist,记录srci-其他顶点最短路径权值数组 dist.resize(n, MAX_W);// vector<int> pPath 记录srci-其他顶点最短路径父顶点数组 pPath.resize(n,-1);// 先更新srci->srci为缺省值 dist[srci]=W();// 总体最多更新n轮for(size_t k =0; k < n;++k){// i->j 更新松弛bool update =false; cout <<"更新第:"<< k <<"轮"<< endl;for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){// srci -> i + i ->jif(_matrix[i][j]!= MAX_W && dist[i]!= MAX_W && dist[i]+ _matrix[i][j]< dist[j]){ update =true;//cout << _vertexs[i] << "->" << _vertexs[j] << ":" << _matrix[i][j] << endl; dist[j]= dist[i]+ _matrix[i][j]; pPath[j]= i;}}}// 如果这个轮次中没有更新出更短路径,那么后续轮次就不需要再走了if(update ==false){break;}}// 还能更新就是带负权回路for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){// srci -> i + i ->jif(_matrix[i][j]!= MAX_W && dist[i]+ _matrix[i][j]< dist[j]){returnfalse;}}}returntrue;}

三、Floyd_Warshall算法

Floyd-Warshall算法是求任意两点之间最短路径的算法,依次把每个点当作中转点,判断从 i 到 j 是直接走更近,还是经过这个中转点 k 再走更近,不断更新所有点对的最短距离,三层循环跑完就得到全图最短路径。

voidFloydWarshall(vector<vector<W>>& vvDist, vector<vector<int>>& vvpPath){ size_t n = _vertexs.size(); vvDist.resize(n); vvpPath.resize(n);// 初始化权值和路径矩阵for(size_t i =0; i < n;++i){ vvDist[i].resize(n, MAX_W); vvpPath[i].resize(n,-1);}// 直接相连的边更新一下for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){if(_matrix[i][j]!= MAX_W){ vvDist[i][j]= _matrix[i][j]; vvpPath[i][j]= i;}if(i == j){ vvDist[i][j]=W();}}}// 最短路径的更新i-> {其他顶点} ->jfor(size_t k =0; k < n;++k){for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){// k 作为的中间点尝试去更新i->j的路径if(vvDist[i][k]!= MAX_W && vvDist[k][j]!= MAX_W && vvDist[i][k]+ vvDist[k][j]< vvDist[i][j]){ vvDist[i][j]= vvDist[i][k]+ vvDist[k][j];// 找跟j相连的上一个邻接顶点// 如果k->j 直接相连,上一个点就k,vvpPath[k][j]存就是k// 如果k->j 没有直接相连,k->...->x->j,vvpPath[k][j]存就是x vvpPath[i][j]= vvpPath[k][j];}}}}}

Read more

C++ 面向对象(类和对象)—— 函数模板

C++ 面向对象(类和对象)—— 函数模板

🎁个人主页:工藤新一¹ 🔍系列专栏:C++面向对象(类和对象篇) 🌟心中的天空之城,终会照亮我前方的路 🎉欢迎大家点赞👍评论📝收藏⭐文章 文章目录 * 模板 * 一、模板简介 * 二、函数模板 * 2.1函数模板的基本语法 * 2.1.1函数模板的调用方式 * 2.2函数模板的注意事项 * 2.4函数模板案例 * 2.5普通函数和函数模板的区别 * 2.5.1隐式类型转换 * 2.6普通函数和函数模板的调用规则 * 2.7模板的局限性 * 2.7.1运算符重载 * 2.7.2具体化模板 模板 * 本阶段主要针对于==C++范式编程和STL技术==进行详细讲解,探讨 C++ 更深层的应用template&

By Ne0inhk
【直接可用源码免费送】计算机毕业设计精选项目:511+外卖点餐系统设计与实现 Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制

【直接可用源码免费送】计算机毕业设计精选项目:511+外卖点餐系统设计与实现 Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制

外卖点餐系统设计与实现 摘  要 随着信息技术的高速发展和网络的广泛应用,外卖点餐服务逐渐成为现代人生活中不可或缺的一部分。为了提高点餐效率和用户体验,本研究引入信息化技术设计并实现一套高效简便且功能齐全的外卖点餐系统。该系统采用Spring Boot框架结合Java语言进行后端开发,利用HTML、CSS和JavaScript等技术构建前端界面,以MySQL数据库作为数据存储核心,并运用RESTful API实现前后端分离的架构。系统主要面向顾客用户和管理员等不同角色,实现了包括注册登录、数据分析、系统用户、系统管理、通知公告管理、资源管理、商城管理等核心功能,基本满足整个外卖点餐、支付、配送及售后等业务流程,有效提升管理效率和服务质量。最终经过功能验证和性能测试,确保系统在实际应用中的可行性和高效性。本系统的实施不仅能够有效整合并管理用户、菜品与订单信息,能够有效提升服务管理效率和用户点餐的便捷性,还提供了实时的数据分析和反馈机制,为决策运营提升提供了支持。同时可以为今后类似外卖点餐系统的开发提供了宝贵参考,具有良好的实践意义和推广价值。 关键词:外卖点餐系统;Spr

By Ne0inhk
C++ 类与对象:封装特性的实现与实战应用

C++ 类与对象:封装特性的实现与实战应用

C++ 类与对象:封装特性的实现与实战应用 💡 学习目标:掌握类与对象的核心概念,理解封装的本质与价值,能够独立设计并实现具有封装特性的 C++ 类。 💡 学习重点:类的定义与对象实例化、访问权限控制、构造函数与析构函数的使用、封装的实战场景应用。 一、类与对象的核心概念 ✅ 结论:类是 C++ 面向对象编程的核心载体,是对一类事物属性和行为的抽象描述;对象是类的具体实例,是内存中实际存在的实体。 1.1 类的组成 一个完整的 C++ 类通常包含两部分: * 成员变量:描述类的属性,如人的姓名、年龄,圆的半径等。 * 成员函数:描述类的行为,如人的吃饭、跑步,圆的面积计算等。 1.2 类的定义格式 #include<iostream>#include<string>

By Ne0inhk
Java SpringBoot+Vue3+MyBatis 医疗挂号管理系统系统源码|前后端分离+MySQL数据库

Java SpringBoot+Vue3+MyBatis 医疗挂号管理系统系统源码|前后端分离+MySQL数据库

摘要 随着信息技术的快速发展,医疗行业的信息化管理需求日益增长。传统的医疗挂号方式存在效率低下、资源分配不均等问题,患者排队时间长、医生工作压力大,严重影响了医疗服务的质量。为了提高医疗资源的利用率,优化患者就医体验,开发一套高效、便捷的医疗挂号管理系统成为迫切需求。该系统通过信息化手段整合医院资源,实现挂号、就诊、管理的全流程数字化,为患者和医务人员提供更加高效的服务。关键词:医疗挂号、信息化管理、资源优化、就医体验、数字化。 本系统采用前后端分离的架构设计,前端使用Vue3框架实现用户界面,后端基于Java SpringBoot框架搭建服务,数据持久化通过MyBatis实现,数据库采用MySQL存储系统数据。系统功能包括患者挂号、医生排班、科室管理、病历查询等模块,支持多角色登录(患者、医生、管理员),并提供数据统计与分析功能,帮助医院优化资源配置。系统设计注重安全性和可扩展性,采用JWT进行身份认证,RESTful API规范接口设计,确保系统稳定高效运行。关键词:前后端分离、SpringBoot、Vue3、MyBatis、多角色登录。

By Ne0inhk