当前位置: 首页 > 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;结点为空结点 **结束时判定该结点的类别遵循如下规则&…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...