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

news2024/11/28 10:33:44

一.迪杰斯特拉算法

首先对于最短路径来说:从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的路上的所有其它的结点;

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

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

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

相关文章

在网上赚钱,可以自由掌控时间,灵活的兼职副业选择

朋友们看着周围的人在网上赚钱&#xff0c;自己也会为之心动&#xff0c;随着电子设备的普及&#xff0c;带动了很多的工作、创业以及兼职副业选择的机会&#xff0c;作为普通人的我们&#xff0c;如果厌倦了世俗的朝九晚五&#xff0c;想着改变一下自己的生活&#xff0c;可以…

STM32 printf 重定向到CAN

最近在调试一款电机驱动板 使用的是CAN总线而且板子上只有一个CAN 想移植Easylogger到上面试试easylogger的效果&#xff0c;先实现pritnf的重定向功能来打印输出 只需要添加以下代码即可实现 代码 #include <stdarg.h> uint8_t FDCAN_UserTxBuffer[512]; void FDCAN_p…

btstack协议栈实战篇--Hello World example

btstack协议栈---总目录-CSDN博客 目录 1.定时计时器设置 2.主要应用程序设置 3.运行log如下图 该示例演示了如何提供周期性定时器来切换LED并将调试消息作为最小BTstack测试发送到控制台。 1.定时计时器设置 由于BTstack中的计时器是单触发的&#xff0c;因此通过在心跳中重新…

从0到1:企业办公审批小程序开发笔记

可行性分析 企业办公审批小程序&#xff0c;适合各大公司&#xff0c;企业&#xff0c;机关部门办公审批流程&#xff0c;适用于请假审批&#xff0c;报销审批&#xff0c;外出审批&#xff0c;合同审批&#xff0c;采购审批&#xff0c;入职审批&#xff0c;其他审批等规划化…

Android Qt开发环境部署

我总结了在Qt中搭建Android开发两个要点&#xff1a; 1.JDK一定要是JDK1.8的 2.要下载目标Android版本的SDK&#xff0c;可以在Android studio SDK查看对应Android SDK版本 下面我们开发搭建。首先需要JDK&#xff0c;链接如下&#xff1a;链接&#xff1a;https://pan.baidu.…

★pwn 24.04环境搭建保姆级教程★

★pwn 24.04环境搭建保姆级教程★ &#x1f338;前言&#x1f33a;Ubuntu 24.04虚拟机&#x1f337;VM&#x1f337;Ubuntu 24.04镜像 &#x1f33a;工具&#x1f337;可能出现的git clone错误&#x1f337;复制粘贴问题&#x1f337;攻击&#x1f337;编题 &#x1f33a;美化&…

【CS.DB】从零到精通:这可能是全网最全面最强大的SQL入门教程

文章目录 1. 什么是SQL&#xff1f;1.1 SQL的历史1.1.1 SQL的标准化过程 2. SQL基础语法2.1 数据库操作2.1.1 创建数据库2.1.2 删除数据库 2.2 表操作2.2.1 创建表2.2.2 删除表2.2.3 修改表 2.3 数据操作2.3.1 插入数据2.3.2 更新数据2.3.3 删除数据 2.4 查询数据2.4.1 基本查询…

【Linux】进程4——进程状态

1.进程状态 什么是状态&#xff1f; 每个人都有状态——颓废&#xff0c;阳光&#xff0c;积极向上。。。。 进程也有状态 在操作系统中&#xff0c;由于进程的数量是非常多的&#xff0c;而系统的资源又非常少&#xff0c;所以不可能每一个进程在每时每刻都会处于上处理机运…

【 技术栈】技术方案到底怎么写?

文章目录 一、背景二、技术方案重要性三、常见的技术方案有哪些内容1、系统用例2、功能整体链路2.1、核心业务流程 3、数据库设计4、接口设计5、非功能设计5.1、性能与稳定性5.2、监控 7、系统风险点评估 四、总结 一、背景 工作中&#xff0c;有一些需求或者技术改造&#xf…

计算机网络--应用层

计算机网络–计算机网络概念 计算机网络–物理层 计算机网络–数据链路层 计算机网络–网络层 计算机网络–传输层 计算机网络–应用层 1. 概述 因为不同的网络应用之间需要有一个确定的通信规则。 1.1 两种常用的网络应用模型 1.1.1 客户/服务器模型&#xff08;Client/Se…

Java面试八股之什么是反射,实现原理是什么

Java中什么是反射&#xff0c;实现原理是什么 Java中的反射&#xff08;Reflection&#xff09;是一种强大的特性&#xff0c;它允许程序在运行时检查和操作类、接口、字段和方法的信息。简而言之&#xff0c;反射机制使得程序能够在运行时动态地了解和使用自身或其他程序集中…

python文件:py,ipynb, pyi, pyc, pyd, pyo都是什么文件?

1、Python文件类型介绍 &#x1f4c1; 1.1 .py 文件&#xff1a;源代码基础 .py 文件是 Python 最基本的源代码文件格式&#xff0c;用于存储纯文本形式的 Python 代码。它是开发者编写程序的主要场所&#xff0c;包含函数、类、变量定义以及执行逻辑。Python 解释器直接读取…

【排序算法】总结篇

✨✨这些 排序算法都是指的 需要进行比较的排序算法 ✨✨下面都是略微讲解一下思路&#xff0c;如果需要详细了解哪一个排序&#xff0c;点击&#x1f449;链接即可 ✨✨对于时间、空间复杂度、稳定性&#xff0c;希望你&#x1f9d1;‍&#x1f393;能够理解记忆&#x1f9d1;…

MyBatisPlus插件生成代码

文章目录 概要安装插件使用插件 概要 MyBatis-Plus 是 MyBatis 的增强工具&#xff0c;旨在简化 MyBatis 的开发。MyBatis-Plus 代码生成器插件可以自动生成项目中常见的代码&#xff0c;如实体类、Mapper 接口、Service 接口和实现类、Controller 等&#xff0c;从而减少手动…

python代码中参数的默认值

python中的函数&#xff0c;可以给形参指定默认值。 带有默认值的参数&#xff0c;可以在调用的时候不传参。 如上图所示&#xff0c;在给函数设定形参的时候可以给函数形参设定默认值&#xff0c;当然默认参数的形参应该在非默认形参的后面。 如果在调用函数的时候&#xff…

SpringBoot整合SpringSecurit(二)通过token进行访问

在文章&#xff1a;SpringBoot整合SpringSecurit&#xff08;一&#xff09;实现ajax的登录、退出、权限校验-CSDN博客 里面&#xff0c;使用的session的方式进行保存用户信息的&#xff0c;这一篇文章就是使用token的方式。 在其上进行的改造&#xff0c;可以先看SpringBoot…

ctfshow-web入门-命令执行(web41_exp与分析)

过滤不严&#xff0c;命令执行 preg_match(/[0-9]|[a-z]|\^|\|\~|\$|\[|\]|\{|\}|\&|\-/i, $c) 过滤掉了数字、字母以及一些符号&#xff0c;之前接触过的无字母 rce 是取反编码再取反&#xff0c;采用不可见字符去绕过正则&#xff0c;但是这里取反符号被过滤掉了&#x…

还在为线上BUG苦苦找寻?试试IntelliJ IDEA远程调试线上Java程序

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

VMware导入小白分享的MacOS版本之后,无法开机的解决方案

前言 这段时间陆续有小伙伴找到小白&#xff0c;说&#xff1a;导入小白分享的MacOS版本之后&#xff0c;出现无法开机的问题。 遇到这个问题&#xff0c;并不是说明分享版本有问题&#xff0c;因为大部分小伙伴导入之后都没有出现类似的问题&#xff0c;都是导入之后开机&…

VBA经典应用69例应用5:使用VBA冻结窗格

《VBA经典应用69例》&#xff08;版权10178981&#xff09;&#xff0c;是我推出的第九套教程&#xff0c;教程是专门针对初级、中级学员在学习VBA过程中可能遇到的案例展开&#xff0c;这套教程案例众多&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以便…