当前位置: 首页 > news >正文

最短路径——迪杰斯特拉与弗洛伊德算法

一.迪杰斯特拉算法

首先对于最短路径来说:从vi-vj的最短路径,不用非要经过所有的顶点,只需要找到路径最短的路径即可;

那么迪杰斯特拉的算法:其实也就与最小生成树的思想类似,找到较小的,然后更新;

首先将dist(路径)长度初始化为两个点之间边的权值,而如果不能一次到达,就是INIFINITY

而迪杰斯特拉算法就是:加点,如果加上中转点之后,再判断此时的最短路径长度,如果此时i-j-k的路径长度小于i-k的,那么此时顶点vi的最短路径就修改为中转路径长度;并且最终将找到的最小路径的终点加入到集合S中,直至所有的顶点都在S中就找到了V0到所有其他顶点的最短路径;

就是判断,更新,但最中间的过程有点麻烦,条件判断也太多;像比于书中的用链表来表示集合的加点,加边,还是实验题中的利用标志数组更为容易,将标志数组变为0/1,这样就不用那么麻烦!!!

下面给出关于迪杰斯特拉算法的完整代码:

#define MAX_VERTEX_NUM 100
#define INFINITY 32768//表示极大值typedef struct
{int vex1;int vex2;int adj_weight;
}Arc;typedef int VertexData;typedef struct ArcNode
{int adj;
}ArcNode;typedef struct
{VertexData vertex[MAX_VERTEX_NUM];ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];int vexnum, arcnum;
}AdjMatrix;//邻接矩阵创建有向图
void CreateDN(AdjMatrix* G,int m)
{int i; int j;int** arr = (int**)malloc(m* sizeof(int*));for (i = 0; i <m; i++){arr[i] = (int*)malloc(m* sizeof(int));}for (i = 0; i < m; i++){for (j = 0; j < m; j++){scanf("%d", &arr[i][j]);}}for (i = 0; i < m; i++){for (j = 0; j <m; j++){if (arr[i][j] != 0){G->arcs[i][j].adj = arr[i][j];}else{G->arcs[i][j].adj = INFINITY;}}}G->vexnum = m;for (i = 0; i <m; i++){free(arr[i]);}free(arr);
}void PrintAdj(AdjMatrix* G)
{for (int i = 0; i <G->vexnum; i++){for (int j = 0; j < G->vexnum; j++){printf("%d ", G->arcs[i][j].adj);}printf("\n");}
}typedef int** PathMatrix;
typedef int* ShortPathTable;
//第五题//path用于保存路径信息,dist用来表示最短路径长度,即边的权值
void ShortestPath_DIJ(AdjMatrix* G, int v0, PathMatrix P, ShortPathTable D)
{int i = 0, j, w, v, min;int final[MAX_VERTEX_NUM];for (v = 0; v < G->vexnum; v++){final[v] = 0;D[v] = G->arcs[v0][v].adj;//从源点到点v的距离,for (w = 0; w < G->vexnum; w++){P[v][w] = 0;//从源点到w点的最短路径是否经过v点//到所有点都设置为不可到达?设置空路径}if (D[v] < INFINITY)//那么初始化的时候,要再加一个附加条件,如果矩阵输入为0,则INFINITY{P[v][v0] = 1; P[v][v] = 1;//小于的话,就存在直接到达的路径//那为什么还要经过v?为什么P???对于矩阵P的意义还是没理解}//从源点到顶点v0中v是中间要经过的}D[v0] = 0;//v0到v0的距离为0;final[v0] = 1;//到自身肯定已经遍历完成//for (i = 1; i < G->vexnum; i++)//这里只代表循环次数,i没有实际的意义//表示剩余的n-1个节点{min = INFINITY;for (w = 0; w < G->vexnum; w++)//有的可能从源点到达不了w,所以一直循环//此时一直循环:{if (!final[w])//说明还没有找到从源点到w的路径{if (D[w] < min){v = w;//此时将v更新为w(不要只注意前两行的,还有后面的//为什么要更新为w呢?//此时v在第一步肯定是要更新的,//然后v就是代表除了v0以外的节点,那么此时也就是从v0到v的已经找到路径min = D[w];}}}//上述过程就是在找到剩下的节点中到达v0的最小的距离final[v] = 1;//见上面的解释//此时就是最终的v才是最后真正访问的w//将final[v]更新以后,他就不再参与后面的运算!就不会与min进行比较//那么就是找出剩余的最短的路径——这就体现了按照路径长度递增的次序for (w = 0; w < G->vexnum; w++){if (!final[w] && (min + G->arcs[v][w].adj) < D[w])//说明找到了//一个更短的路径,这个才是更新路径的判断条件{D[w] = min + G->arcs[v][w].adj;//更新最短路径for (j = 0; j < G->vexnum; j++){P[w][j] = P[v][j];//P有什么用???}P[w][w] = 1;//说明已经完成了所有的遍历?因为在循环中,所有的都设置为1了}}}for (i = 0; i < G->vexnum; i++){if (i != v0){if (D[i] < INFINITY){printf("%d ", D[i]);}else{printf("-1 ");}}}
}int main()
{AdjMatrix G;//G = (AdjMatrix*)malloc(sizeof(AdjMatrix));int m, n;scanf("%d %d",&m, &n);CreateDN(&G, m);//PrintAdj(G);PathMatrix p;p = (int**)malloc(G.vexnum*sizeof(int*));for (int i = 0; i < m; i++){p[i] = (int*)calloc(G.vexnum,sizeof(int));}ShortPathTable D;D = (int*)malloc(m*sizeof(int));for (int i = 0; i <m; i++){D[i] =INFINITY;}//别忘了把n加1;ShortestPath_DIJ(&G, n, p, D);return 0;
}

二.弗洛伊德算法

若是求任意两个顶点之间的最短路径,就可以将每一个顶点作为源,多次调用迪杰斯特拉算法就可以找到任意两个顶点之间的最短路径,而利用弗洛伊德算法:就可以直接利用三重循环求出任意两点间的最短路径;

弗洛伊德算法最重要的就是要理解三重循环:

首先理解一下path:这个数组是存放i->j的最短路径的前驱结点,也就是距离j结点的最近的一个结点;

这时候:会有一个疑问,只存放一个前驱结点,那如何打印出路径上的所有结点呢?

有这个疑问就是没有理解三重循环的含义:假设i->j的前驱节点path[i][j]=p;

而p也是属于其他所有结点中的一个结点,那么自然也会有从i->p的最短路径,假设i->p的最短路径的前驱结点为m,那么i....m->p->j;也就是说,m也是属于从i->j的最短路径上的结点(因为单个值最小,所有的单个值的和肯定也最小,m,是保证从i->p的路径最短的点,那么m理应属于i->j的最短路径)以此类推直到找到距离i最近的前驱节点;此时也就找出了从顶点i到达任意所有其他结点的最小路径;而i->j的路径也就在这个过程中能够全部得出来!

综上所述:三层循环得本质我们就可以得到:i,j两层循环是作为二维数组的下标i,j;而表示从结点i到达结点j,而k则是可以作为前驱节点(中间结点)因为前驱节点肯定是在所有结点中间的,所以这层k的循环就代表这个意思;最终就能够找到所有的由顶点i到其他所有结点的最小路径;

而在打印路径的时候,根据上面的理解,path[i][j]只代表一个结点,那难道就只能打印一个结点吗?

根据上面的理解,我们既然可以找到i->j的前驱节点k,那么自然也能找到i->k的前驱结点,以此类推,递归下去,就能找到i->j的路上的所有其它的结点;

所以打印的过程是个递归的过程;

相关文章:

最短路径——迪杰斯特拉与弗洛伊德算法

一.迪杰斯特拉算法 首先对于最短路径来说&#xff1a;从vi-vj的最短路径&#xff0c;不用非要经过所有的顶点&#xff0c;只需要找到路径最短的路径即可&#xff1b; 那么迪杰斯特拉的算法&#xff1a;其实也就与最小生成树的思想类似&#xff0c;找到较小的&#xff0c;然后…...

6.7.11 一种新的迁移学习方法可提高乳房 X 线摄影筛查中乳腺癌的诊断率

分割是一种将图像分割成离散区域的技术&#xff0c;以便将感兴趣的对象与周围环境分开。为了制定治疗计划&#xff0c;分割可以帮助医生测量乳房中的组织量。 二元分类问题的目的是将输入数据分为两组互斥的数据。在这种情况下&#xff0c;训练数据根据要解决的问题以二进制格…...

【Proteus8.16】Proteus8.16.SP3.exe的安装包,安装方法

下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/14ZlETF7g4Owh8djLaHwBOw?pwd2bo3 提取码&#xff1a;2bo3 管理员打开proteus8.16.SP3.exe一路装就行了&#xff0c;许可证选Licence2.lxk,点安装后关闭&#xff0c;然后继续装完。 然后打开Patch-Proteus-8.16-…...

17、matlab实现均值滤波、中值滤波、Butterworth滤波和线性相位FIR滤波

1、创建信号 1&#xff09;创建正余弦信号、噪声信号和混合信号 原始正余弦信号公式&#xff1a;Signal1 sin(2*pi*20* t) sin(2*pi*40* t) sin(2*pi*60* t) 高斯分布的白噪声&#xff1a;NoiseGauss [randn(1,2000)] 均匀分布的白噪声&#xff1a;[rand(1,2000)] 正余弦…...

【Autopilot】没有自动添加本地管理员的问题处理

【问题】某公司选用了D记的笔记本电脑&#xff0c;约定出厂就预配置好Autopilot&#xff0c;当时向D记提供了三个信息&#xff1a; 1. M365的租户ID 2. 公司域名信息 3. Group Tag (某公司为跨国公司&#xff0c;通过Group Tag来区分国家&#xff0c;比如CHN-中国&#xff0c;L…...

【C#学习笔记】属性和字段

文章目录 前言属性和字段的区别字段访问修饰符和关键字定义变量类型的定义变量命名变量的赋值 属性 不同的使用情况 前言 最近在工作的过程中常常会觉得自己在程序设计方面的能力还是有欠缺。例如一直对于变量的声明感到不足&#xff0c;在工作中为了图方便总是直接public定义…...

最佳实践的实践 - API 不应将 HTTP 重定向到 HTTPS

原文&#xff1a;jviide - 2024.05.23 TL;DR: 与其将 API 调用从 HTTP 重定向到 HTTPS&#xff0c;不如让失败显而易见。要么完全禁用 HTTP 接口&#xff0c;要么返回明确的 HTTP 错误响应&#xff0c;并撤销通过未加密连接发送的 API 密钥。遗憾的是&#xff0c;许多知名的 A…...

四种跨域解决方案

文章目录 1.引出跨域1.基本介绍2.具体演示1.启动之前学习过的springboot-furn项目2.浏览器直接访问 [localhost:8081/furns](http://localhost:8081/furns) 可以显示信息3.启动前端项目&#xff0c;取消请求拦截器&#xff0c;这样设置&#xff0c;就会出现跨域4.跨域原因 2.跨…...

移动端投屏到大屏幕的操作详解

如果你懒得折腾电脑、电视或其他大屏设备上的影视软件安装及配置&#xff0c;可以选择直接在手机端上将影片投屏到电脑、电视或其他大屏设备上&#xff0c;这里给大家分享三种手机投屏的方法。 系统自带的投屏功能 不管是安卓、鸿蒙还是苹果操作系统&#xff0c;都自带了无线…...

【环境搭建】3.阿里云ECS服务器 安装Redis

在阿里云的 Alibaba Cloud Linux 3.2104 LTS 64位系统上安装 Redis 可以通过以下步骤完成&#xff1a; 1.更新系统软件包&#xff1a; 首先&#xff0c;更新系统软件包以确保所有软件包都是最新的&#xff1a; sudo yum update -y2.安装编译工具和依赖项&#xff1a; Redis…...

动态语言的开源编译器汇总

对于动态语言而言&#xff0c;我们通常不会使用传统意义上的“编译器”&#xff0c;因为动态语言往往是在运行时解释执行的&#xff0c;或者被转换为中间形式&#xff08;如字节码&#xff09;&#xff0c;再由虚拟机执行。不过&#xff0c;为了性能考虑&#xff0c;现代动态语…...

Linux防火墙配置001

Linux防火墙主要用于控制网络流量&#xff0c;保护系统安全。在Linux中&#xff0c;有几种不同的防火墙管理工具&#xff0c;其中最常见的是iptables和firewalld。本章主要讲述如何关闭防火墙。 操作系统&#xff1a; CentOS Stream 9 操作步骤&#xff1a; 关闭防火墙&…...

Tomcat概述及部署

目录 一.Tomcat概述 1.介绍 2.使用场景 3.组件构成 4.组件结构 5.请求过程 二.Tomcat部署 1.关闭防火墙 2.下载安装JDK 3.安装启动tomcat 4.部署虚拟主机 4.1.创建 xy101 和 xy102 项目目录和文件 4.2.修改 Tomcat 主配置文件 server.xml 一.Tomcat概述 1.介绍 …...

[Vue3:Vite构建项目]:安装router实现登录页面路由跳转

文章目录 一&#xff1a;前置依赖查看依赖安装vite npm create vitelatest sys-instruction-0607 --template vue-ts安装路由&#xff1a;npm install vue-router4安装elementUI&#xff1a;npm install element-plus --save 二&#xff1a;配置文件&#xff1a;views&#xff…...

概率论与数理统计,重要知识点——全部公式总结

二、一维随机变量及其分布 五个分布参考另外一篇文章 四、随机变量的数字特征 大数定理以及中心极限定理 六、数理统计...

Spring系列-SpringMvc父子容器启动原理解析

1、Spring整合SpringMVC 特性&#xff1a; 说到Spring整合SpringMVC唯一的体现就是父子容器&#xff1a; 通常我们会设置父容器&#xff08;Spring&#xff09;管理Service、Dao层的Bean, 子容器(SpringMVC)管理Controller的Bean .子容器可以访问父容器的Bean, 父容器无法访…...

[ssi-uploader插件]解决如何接收服务器返回数据+修改参数名称

前言 ssi-uploader是一款非常好用的多文件上传插件&#xff0c;源码是开源的&#xff0c;在github上面即可下载&#xff1a; https://github.com/ssbeefeater/ssi-uploader 但是源码有些微小的不足&#xff0c;今天我们解决两点问题&#xff1a; 上传文件完成后&#xff0c…...

InfiniGate自研网关实现思路七

25.网关Nginx负载模型配置 通过模拟多个HTTP服务配置到 Nginx 做负载均衡&#xff0c;以学习API网关负载的配置和使用 API 网关是用于支撑分布式 RPC 接口协议转换提供 HTTP 调用的一套服务&#xff0c;那么 API 网关系统就需要可横向扩展来满足系统的吞吐量诉求。所以这里需…...

277 基于MATLAB GUI火灾检测系统

基于MATLAB GUI火灾检测系统&#xff0c;可以实现图片和视频的火苗检测。火焰识别的三个特征&#xff1a;1个颜色特征&#xff0c;2个几何特征颜色特征&#xff1a;HSV颜色空间下&#xff0c;对三个通道值进行阈值滤波&#xff0c;几何特征1&#xff1a;长宽比&#xff0c;几何…...

【西瓜书】4.决策树

1 递归返回情况 &#xff08;1&#xff09;结点包含样本全为同一类别 &#xff08;2&#xff09;属性集为空&#xff0c;没有属性可供划分了 或 有属性&#xff0c;但是在属性上划分的结果都一样 &#xff08;3&#xff09;结点为空结点 **结束时判定该结点的类别遵循如下规则&…...

区块链--Ubuntu上搭建以太坊私有链

1、搭建私链所需环境 操作系统&#xff1a;ubuntu16.04&#xff0c;开虚拟机的话要至少4G&#xff0c;否则会影响测试挖矿时的速度 软件&#xff1a; geth客户端 Mist和Ethereum Wallet&#xff1a;Releases ethereum/mist GitHub 2、安装geth客户端 sudo apt-get update …...

菜品信息分页查询——后端SpringBoot

1.分页查询的逻辑&#xff1a; 页面发送ajax请求&#xff0c;将分页查询参数(page&#xff0c;pageSize, name)提交到服务端&#xff0c;获取分页数据&#xff1b; 页面发送请求&#xff0c;请求服务端进行图片下载&#xff0c;用于页面图片展示。 开发菜品信息分页查询功能&a…...

利用GPT和PlantUML快速生成UML图用于设计

在软件开发中&#xff0c;设计阶段可是关键的一步。UML&#xff08;统一建模语言&#xff09;图能帮我们更清晰地理解和规划系统结构&#xff0c;但手动画UML图有时会很费时费力。好消息是&#xff0c;通过结合使用ChatGPT和PlantUML&#xff0c;我们可以高效地生成UML图&#…...

web-上传项目文件夹到Git远程仓库

Git初识 概念&#xff1a;一个免费开源&#xff0c;分布式的代码版本控制系统&#xff0c;帮助开发团队维护代码 作用&#xff1a;记录代码内容&#xff0c;切换代码版本&#xff0c;多人开发时高效合并代码内容 检验成功 打开bash终端&#xff08;git专用&#xff09;命令…...

使用OpenPCDet训练与测试Transformer模型:如何加载自己的数据集

引言 Transformer架构因其强大的序列处理能力和长距离依赖捕捉能力&#xff0c;在自然语言处理领域取得了巨大成功。近年来&#xff0c;这一架构也被引入3D物体检测领域&#xff0c;如Voxel Transformer等&#xff0c;显著提升了模型在复杂场景下的检测性能。OpenPCDet整合了多…...

四舍五入问题

单纯输出四舍五入可以用 printf("%.nf",num); 但是这个方法有时候会出错 代表输出n位四舍五入小数 而将数四舍五入赋值给变量可以用round&#xff08;&#xff09;函数 a round(num); 表示将num四舍五入赋值给a 但是这么些只能转换位四舍五入的整数 可以改…...

零基础入门学用Arduino 第一部分(三)

重要的内容写在前面&#xff1a; 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后&#xff0c;整体感觉是很好的&#xff0c;如果有条件的可以先学习一些相关课程&#xff0c;学起来会更加轻松&#xff0c;相关课程有数字电路…...

C++标准库random

random 完整文档看这里 三步走: 选择一种随机数种子选择一个随机数引擎选择一个随机数分布输出 随机数种子 //生成随机数种子,在Linux的实现中,是读取/dev/urandom设备 std::random_device rd; unsigned seed1 rd();// 获取当前时间点作为随机数种子 unsigned seed2 std:…...

电子电气架构——车载诊断DTC一文通

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在世,最怕的就是把别人的眼光当成自己生活的唯一标…...

Golang | Leetcode Golang题解之第129题求根节点到叶节点数字之和

题目&#xff1a; 题解&#xff1a; type pair struct {node *TreeNodenum int }func sumNumbers(root *TreeNode) (sum int) {if root nil {return}queue : []pair{{root, root.Val}}for len(queue) > 0 {p : queue[0]queue queue[1:]left, right, num : p.node.Left, …...

做任务领黄钻的网站/网络运营培训

删除逻辑 boolean del(taskName任务名称, busNo业务编号) keyqlscf_taskName_busNo 如果key存在 getRedisTemplate().delete(key) 获取逻辑 boolean get(taskName任务名称, busNo业务编号) keyqlscf_taskName_busNo 如果key存在 取出redis中key对应的value&#xff1a;getRe…...

wordpress+迁移后空白/百度网页版

JSP和SERVLET区别 JSP和SERVLET到底在应用上有什么区别&#xff0c;很多人搞不清楚。我来胡扯几句吧。简单的说&#xff0c;SUN首先发展出SERVLET&#xff0c;其功能比较强劲&#xff0c;体系设计也很先进&#xff0c;只是&#xff0c;…...

临沂网站建设公司全国/惠州网站seo

有的时候&#xff0c;大家可能会遇到这种需求&#xff1a;显示某个物体的线框&#xff0c;就像汽车设计图纸&#xff08;CAD之类的&#xff09;那样。例如下面这种效果&#xff1a; 效果1&#xff1a; 效果2&#xff1a; 用shader就可以解决这个问题。甚至可以不写代码&#x…...

金陵热线 网站备案/站长交流平台

使用新浪SAE架构搭建自己的网站。将自己在本地编写的PHP程序上传到SAE上。如果要正常使用需要链接MySQL数据库(如果你的网站使用了MySQL数据库服务)。新浪SAE提供了对PHP访问MySQL的程序支持。所以这个过程要实现起来并不困难。只需要修改用户名和密码。创建完应用后&#xff0…...

怎么做直播室的网站/灰色词排名上首页

第一部分需要三个步骤&#xff1a; 选择输入步骤&#xff0c;“生成记录”&#xff0c;将步骤里设置记录数为1&#xff0c;并设置一个类型为String的字段country&#xff08;名字随便&#xff09;&#xff0c;这个字段的值应设置为我们要抽取数据的URL&#xff0c;如&#xff1…...

百度官方网站怎么做/网上接单平台有哪些

和IOS开发和Windows Phone开发相比&#xff0c;Android是开放的&#xff0c;Android上的开发也相对更加灵活&#xff0c;能够做很多事情。有的朋友会发现&#xff0c;在某些Android应用安装以后&#xff0c;第一次运行&#xff0c;就会在桌面创建快捷方式。这是如何做到的呢&am…...