求图的最短路径长度的弗洛伊德(Floyd)算法

弗洛伊德算法的适用情况:弗洛伊德算法既可以用来求解有向网的最短路径长度,也可以用来求无向网的最短路径长度,但是对于图中出现负权环的情况,弗洛伊德无法的得到正确的答案

弗洛伊德的算法思想:

以此图为例讲解弗洛伊德算法的算法步骤:

 

  1. 第一步将图用邻接矩阵的数据结构存储,得到一张二维表记作ArcInfor,顶点到其自身的边权值记为0,若两个顶点之间没有直达的边则即为无穷大,如图所示:对于图的邻接矩阵的存储结构不了解的读者可以去看我的这篇博客:http://t.csdn.cn/aQaTI这篇博客里面讲了图的基本知识以及图的顺序存储方式(邻接矩阵)以及链式存储方式(邻接表)的实现过程,就是有点长可能需要一点耐心才可以看的下去
  2. 第二步,以0作为中间顶点,求每一个顶点经过顶点0到达其他顶点的路径长度,若该长度小于上表表项,则更新上表,比如以0为中间结点,求顶点2途径中间顶点0到达顶点3的路径长度为:ArcInfor[2][0[+ArcInfor[0][3]=10>ArcInfor[2][3],因此不更新此表项
  3. 第三步就是重复第二步依次将其他顶点作为中间顶点,然后求每一个顶点途径此顶点到达其它顶点的路径长度,然后符合条件就更新表项,最终得到的二维表arc中就记录了任意两对顶点之间的最短路径的长度

从以上算法思想我们已经可以得到一个大致的思路就是弗洛伊德算法只需要借助简单的三重for循环就可以实现,如

void FloydAlgorithm(int v[V],int arc[V][V],int spath[V][V])
{//只需要用到三重for循环即可实现弗洛伊德算法for (int k = 0; k < V; k++){for (int i = 0; i < V; i++){for (int j = 0; j < V; j++){if (arc[i][k] + arc[k][j] < arc[i][j]){arc[i][j] = arc[i][k] + arc[k][j];spath[i][j] = k;}}}}//打印最短路径print_spath(v, arc, spath);}

 最外层循环控制变量是用于实现步骤“依次将每一个顶点作为中间顶点“,而内层的两层循环是用于实现”以某个顶点作为中间节点时,每一个顶点经过此结点到达其它顶点的最短路径“;

对于这题,我们不禁想要得到一个简单的最短路径长度,我们还期望得到任意两个顶点之间的最短路径,即将路径上途径的顶点输出;这里我们需要借助一个二维矩阵spath来实现,spath[i][j]的含义是,顶点i与j之间的中间顶点;输出对最短路径的代码如下,对于输出最短路径的代码,读者可能不是很清楚,这时候可以把我的代码调试一遍,观察各个变量取值的变化情况,这样你就能理解算法的设计思路了,对于我来说,我每次看不太懂别人的代码的时候用的都是此方法

//以下函数用于输出两个顶点之间的最短路径间需要经过那些顶点,不包括源节点和目的节点
void output(int v[V],int spath[V][V],int start,int end)         //start,end表示的是顶点所在的数组中的下标。
{//该函数需要用到递归思想,我们从右往左输出源节点到目的节点所经过的顶点的信息int k = spath[start][end];         //即从start到end中间需要经过的一个顶点再顶点数组中的下标if (k == -1){return;}output(v, spath, start, k);printf("%d->", v[k]);output(v, spath, k, end);
}//以下函数用于打印图中任意两个结点之间的最短路径
void print_spath(int v[V],int arc[V][V],int spath[V][V])
{for (int i = 0; i < V; i++){for (int j = 0; j < V; j++){if (i == j){continue;}else{if (arc[i][j] >= INF){printf("%d->%d之间不存在路径\n", v[i], v[j]);}else{printf("%d->%d之间的最短路径长度为:%d\n", v[i],v[j],arc[i][j]);printf("%d->%d之间的最短路径为:\n", v[i], v[j]);printf("%d->", v[i]);output(v, spath, i, j);printf("%d\n", v[j]);}}}}
}

完整程序源代码以及运行结果截图:

程序源代码:


//用弗洛伊德算法求图的最短路径//弗洛伊德算法既可以用来求无向图的最短路径,也可以用来求有向图的最短路径;//注意:弗洛伊德算法不可以用于求存在负权环的图的最短路径#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>#define V 4     //顶点的数目 
#define INF 60000         //用于定义一个大数,当两个顶点之间不存在边或者弧时,在邻接矩阵中的对应位置上填上该大数,infinity:无穷大//采用邻接矩阵的方式来存储图的边的信息//以下函数用于输入图的边的顶点信息和边的信息
void input(int *v,int arc[V][V]);//以下函数用于实现弗洛伊德算法void FloydAlgorithm(int v[V], int arc[V][V], int spath[V][V]);//以下函数用于输出两个顶点之间的最短路径间需要经过那些顶点,不包括源节点和目的节点
void output(int v[V], int spath[V][V], int start, int end);//以下函数用于打印图中任意两个结点之间的最短路径
void print_spath(int v[V], int arc[V][V], int spath[V][V]);int main()
{int vertex[V];         //用于存放图的顶点信息int ArcInfor[V][V];          //用于存放图的边的信息int spath[V][V];            //用于记录两个顶点之间的最短路径for (int i = 0; i < V; i++){for (int j = 0; j < V; j++){spath[i][j] = -1;}}//输入图的弧的信息和边的信息input(vertex, ArcInfor);//求最短路径FloydAlgorithm(vertex, ArcInfor, spath);return 0;}void input(int* v, int arc[V][V])
{printf("请输入图的顶点信息:\n");for (int i = 0; i < V; i++){scanf("%d", &v[i]);}printf("请输入图的边的信息:\n");for (int i = 0; i < V; i++){for (int j = 0; j < V; j++){scanf("%d", &arc[i][j]);}}}//以下函数用于输出两个顶点之间的最短路径间需要经过那些顶点,不包括源节点和目的节点
void output(int v[V],int spath[V][V],int start,int end)         //start,end表示的是顶点所在的数组中的下标。
{//该函数需要用到递归思想,我们从右往左输出源节点到目的节点所经过的顶点的信息int k = spath[start][end];         //即从start到end中间需要经过的一个顶点再顶点数组中的下标if (k == -1){return;}output(v, spath, start, k);printf("%d->", v[k]);output(v, spath, k, end);
}//以下函数用于打印图中任意两个结点之间的最短路径
void print_spath(int v[V],int arc[V][V],int spath[V][V])
{for (int i = 0; i < V; i++){for (int j = 0; j < V; j++){if (i == j){continue;}else{if (arc[i][j] >= INF){printf("%d->%d之间不存在路径\n", v[i], v[j]);}else{printf("%d->%d之间的最短路径长度为:%d\n", v[i],v[j],arc[i][j]);printf("%d->%d之间的最短路径为:\n", v[i], v[j]);printf("%d->", v[i]);output(v, spath, i, j);printf("%d\n", v[j]);}}}}
}void FloydAlgorithm(int v[V],int arc[V][V],int spath[V][V])
{//只需要用到三重for循环即可实现弗洛伊德算法for (int k = 0; k < V; k++){for (int i = 0; i < V; i++){for (int j = 0; j < V; j++){if (arc[i][k] + arc[k][j] < arc[i][j]){arc[i][j] = arc[i][k] + arc[k][j];spath[i][j] = k;}}}}//打印最短路径print_spath(v, arc, spath);}

 运行结果截图:

祝学习进步,生活愉快! 

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

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

相关文章

chatgpt赋能python:Python中如何输入中文——从安装到常见问题解决

Python中如何输入中文——从安装到常见问题解决 Python是一门广泛使用的编程语言&#xff0c;其优秀的开源性、易用性、灵活性以及庞大的生态圈也令越来越多的人选择Python。但是对于初学者来说&#xff0c;如何正确输入中文常常成为一个问题。本篇文章从安装、常见问题解决、…

手机快充协议介绍

手机快充协议介绍 原文链接&#xff1a;https://zhuanlan.zhihu.com/p/448677383 目前市面上的手机充电器五花八门&#xff0c;手机厂商发布的手机支持多种快充协议&#xff0c;这些协议有公有的&#xff0c;有私有的&#xff0c;什么PD、SCP/FCP、VOOC等等&#xff0c;消费者…

转区系统开放艾欧尼亚转入服务器,LOL转区系统申请客户端及操作流程介绍

LOL转区系统申请地址及操作流程介绍。目前LOL转区系统已经率先开始测试&#xff0c;暂时只开放了支持艾欧尼亚、比尔吉沃特以及黑色玫瑰三个大区专区&#xff0c;而且只能转入男爵领域大区。下面是LOL专区系统申请地址以及相关介绍教程。 第一期体验测试时间&#xff1a; 7月28…

LOL各大服务器所在位置,LOL各大服务器所在地,8个大区全都在广东,是其他省的两倍...

现在电竞行业是很多人在关注的&#xff0c;我们看到电竞行业热度一高&#xff0c;也带动了玩家的热度&#xff0c;玩家数量在不断的上升&#xff0c;就目前的数据看&#xff0c;英雄联盟是目前游戏玩家数量最多的端游&#xff0c;电竞比赛也是最多人关注的&#xff0c;就目前的…

王者荣耀专区系统服务器繁忙,王者荣耀:角色转区系统终于正式开放,想要转区必须注意这5点!...

当然&#xff0c;这个选择可以是买一个自己比较钟意的皮肤&#xff0c;毕竟最终账号的皮肤也会随着旧账号一起转移到新账号上去&#xff0c;如果点券不够的话&#xff0c;建议可以充一点&#xff0c;最近天美给力的活动还是蛮多的&#xff0c;譬如&#xff1a;王昭君-偶像歌手星…

lol比赛服 服务器文件,LOL比赛服转换文件

OL比赛服转换文件是一款可以将电脑中安装的lol英雄联盟客户端替换成比赛服&#xff0c;从而避免专门下载比赛服安装的麻烦&#xff0c;用户在使用此软件前请一定要仔细阅读下面的操作&#xff0c;防止游戏无法正常运行。 使用说明 1.把文件“dirserver.xml”放进路径&#xff1…

王者荣耀账号转服务器,《王者荣耀》账号怎么转区 账号转区方法

导 读 本次给大家带来的是王者荣耀的账号迁移功能解释&#xff0c;相信不少玩家都知道可以账号迁移了&#xff0c;但是并不清楚应该怎么做&#xff0c;目前这个功能还没有正式上线&#xff0c;但是可以先教大家方法&#xff0c;感兴趣的小伙伴可以看一下哦~ 王者荣耀账... 本次…

基于深度学习的高精度野生目标检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度野生目标检测识别系统可用于日常生活中检测与定位野生目标目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的野生目标目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测…

lol服务器位置2017,2017LOL转区系统在哪儿 LOL12月转区系统地址入口

&#xfeff;LOL又再次开放了转区系统了&#xff0c;这次转区在哪儿申请呢&#xff1f;很多玩家还不是特别清楚&#xff0c;今天小编便给大家带来2017LOL转区系统的地址入口&#xff0c;一起来看看在哪儿可以进行转区吧。 LOL12月转区系统地址入口&#xff1a; 【转区地址】点击…

Flutter问题记录 - TextField组件多行提示文本显示不全

文章目录 前言开发环境问题描述问题分析解决方案最后 前言 梳理Flutter项目的过程中发现还有一些遗留的TODO没处理&#xff0c;其中有一个和TextField组件相关。 开发环境 Flutter: 3.10.1Dart: 3.0.1 问题描述 TextField组件设置maxLines: null不限制行数&#xff0c;同时…

Seata 分布式事务-应用实例

Seata 分布式事务-应用实例 需求分析/图解 需求&#xff1a;完成下订单功能&#xff0c;由三个微服务模块协同完成, 涉及到多数据库, 多张表 分析 黑色线是执行顺序线 红色线是想Seata Server注册 最后紫色线是决定是否提交和回滚 项目目录 主题包结构都是一样的但是类名字…

chatgpt赋能python:Python中的字符提取:从基础到高级

Python中的字符提取&#xff1a;从基础到高级 在使用Python进行文本处理和数据挖掘时&#xff0c;我们经常需要从字符串中提取特定的字符或子串。本文将介绍Python中的常用字符串提取方法&#xff0c;包括基础的字符串操作、正则表达式和第三方库等高级方法。 基础字符串操作…

chatgpt赋能python:Python中用什么表示空值?

Python中用什么表示空值&#xff1f; 在Python编程中&#xff0c;我们经常会遇到处理空值的场景。空值通常表示缺失的或未定义的值&#xff0c;这在数据处理和分析中尤其常见。那么&#xff0c;在Python中&#xff0c;究竟用什么来表示空值呢&#xff1f; None 在Python中&a…

ENU、EPSG坐标系科普(三维重建)

ENU和EPSG实际上代表了两个不同的概念&#xff0c;这两者并不是直接对比的。 1. ENU坐标系&#xff1a;ENU坐标系是一种本地切面坐标系&#xff0c;用于表示与地理位置相关的空间数据。在ENU坐标系中&#xff0c;E代表东&#xff08;East&#xff09;&#xff0c;N代表北&…

ps中给图层新建文件夹

快捷键&#xff1a;CtrlG 或者点击菜单中–图层–新建–组

3.photoshop 图层的创建与管理

xmind: https://github.com/wangtao-luse/static

高速缓存(cache)的原理: 了解计算机架构与性能优化

计基之存储器层次结构 Author&#xff1a; Once Day Date&#xff1a; 2023年5月9日 长路漫漫&#xff0c;而今才刚刚启程&#xff01; 本内容收集整理于《深入理解计算机系统》一书。 参看文档: 捋一捋Cache - 知乎 (zhihu.com)iCache和dCache一致性 - 知乎 (zhihu.com)C…

chatgpt赋能python:Python中拷贝的介绍

Python 中拷贝的介绍 在 Python 中&#xff0c;拷贝是一个十分常见而且必要的操作。拷贝可以在许多情况下被使用&#xff0c;例如在创建测试数据、编写一个新的算法时&#xff0c;或者是在处理多维数据结构的程序中。由于 Python 中的对象是动态类型的&#xff0c;因此在拷贝时…

色情版“微信”背后的秘密

作者&#xff1a;暗影安全实验室 来源&#xff1a;https://www.anquanke.com/post/id/219729 背景&#xff1a;近日&#xff0c;恒安嘉新暗影安全实验室平台监测到一款名为“乐宝”的仿冒应用&#xff0c;安全研究人员第一时间对该应用进行了研究分析&#xff0c;发现该应用表面…

微信的秘密-python可视化微信好友信息

记得2016年第一次开通微信的时候&#xff0c;我以及周围的大多数人还是重度的QQ用户&#xff0c;当时只是跟风开通了一下&#xff0c;也没觉得会改变什么。没想到才两年过去&#xff0c;我已经忘记了QQ的存在&#xff0c;每天起来第一件事就是查看微信&#xff0c;睡觉前也必然…