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

数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。

文章目录

  • 前言
  • 一、单源最短路径
    • 1、单源最短路径问题
    • 2、Dijkstra 初始化
      • a、参数
      • b、初始化参数
      • c、算法步骤
    • 3、Dijkstra 算法详细步骤
      • a、第一轮算法执行
      • b、第二轮算法执行
      • c、第三轮算法执行
      • d、第四轮算法执行
      • e、第五轮算法执行
      • f、第六轮算法执行
    • 4、java算法实现
  • 二、多源最短路径
    • 1、多源最短路径问题
    • 2、Floyd初始化
      • a、参数
      • b、参数初始化
      • c、算法步骤
    • 3、Floyd算法详细步骤
    • 4、java 算法实现

前言

  • 最短路径的算法有两个,Dijkstra算法 和 Floyd算法
  • Dijkstra算法 解决的是 单源 最短路径问题
  • Floyd算法解决的是 多源 最短路径问题,并且可以处理负权图
  • 今天要讲的就是Dijkstra算法。
  • 加:feng--Insist(大写的i),进java交流群讨论互联网+技术。可索要PPT等资料。
  • 其他资料,建议先看本篇博客。:Dijkstra算法和Floyd算法:https://blog.csdn.net/weixin_43872728/article/details/100662957
  • 代码位置:https://github.com/fengfanli/dataStructuresAndAlgorithm/tree/master/src/com/feng/algorithm/self_learn

一、单源最短路径

1、单源最短路径问题

  • 解决的问题: 求解单源最短路径,即各个节点到达源点的最短路径或权值。如下图中
    在这里插入图片描述
    考察其他所有节点到源点的最短路径和长度
  • 局限性: 无法解决权值为负数的情况
  • 资料
    • 可先看匹配视频:https://www.bilibili.com/video/BV1o44y1B7NM/
    • 代码:待上传。

2、Dijkstra 初始化

首先已知的是:
给定 邻接矩阵表示的图Graph、源点S、终点T

a、参数

参数:

参数名解释
S记录当前已经处理过的源点到最短节点
U记录还未处理的节点
dist[]记录各个节点到起始节点的最短权值
path[]记录各个节点的上一级节点(用来联系该节点到起始节点的路径)

b、初始化参数

  • 顶点集S: 节点A到自已的最短路径长度为0。只包含源点,即S={A},代码中没有这个,这里是为了步骤清晰而设置的。
  • 顶点集U: 包含除A外的其他顶点. 即U={B,C,D,E,F,G}
  • dist[]: 源点还不能到达的节点,其权值为∞
ABCDEFG
dist[]:0123456
初始化值:0466

path[]: 记录当前节点的前驱节点下标(源点还不能到达的节点为-1)

ABCDEFG
path[]:0123456
初始化值:0000-1-1-1

c、算法步骤

在这里插入图片描述

  1. 初始化:设定除源节点以外的其它所有节点到源节点的距离为INFINITE(一个很大的数),且这些节点都没被处理过。如上图所示
  2. 从源节点出发,更新相邻节点(图中为B、C、D)到源节点的距离。然后在所有节点中选择一个最段距离的点作为当前节点。
  3. 标记当前节点为done(表示已经被处理过),与步骤2类似,更新其相邻节点的距离。(这些相邻节点的距离更新也叫 松弛,目的是让它们与源节点的距离最小。因为你是在当前最小距离的基础上进行更新的,由于当前节点到源节点的距离已经是最小的了,那么如果这些节点之前得到的距离比这个距离大的话,我们就更新它)。
  4. 步骤3做完以后,设置这个当前节点已被done,然后寻找下一个具有最小代价(cost)的点,作为新的当前节点,重复步骤3.
  5. 如果最后检测到目标节点时,其周围所有的节点都已被处理,那么目标节点与源节点的距离就是最小距离了。如果想看这个最小距离所经过的路径,可以回溯,前提是你在步骤3里面加入了当前节点的最优路径前驱节点信息。
  • 我总结了下可用如下几句话代替:
    两步走
    1. 从dist[]中在集合U中的选择最小距离加入到S中,作为当前节点。(最小距离:就是 当前节点到源点的最小距离)
    2. 遍历当前节点的邻边节点:更新dist[]和path[]
      • 如果经过当前节点+邻边权重 < 邻边节点,则改变dist[]和path[],否者不改变。

3、Dijkstra 算法详细步骤

a、第一轮算法执行

在这里插入图片描述

  • 如上图,因为dist[]中排出掉集合U中节点,最小值是4,也就是节点B,所以将B纳入到集合S中(圈中)。

  • 首先 在dist[]数组中并在集合U中 最小值是节点B,既当前节点,其邻边有C和E,所以看是否要更新C和E。

    • 节点C:因为C的最小距离dist[1](B的最小距离)4+1(B到C的距离)=5 < dist[2](C的最小距离) = 6,所以 dist[2]=5,path[2]=1
    • 节点E:因为E的最小距离 dist[1](B的最小距离)4+7(B到E的距离)=11 < dist[4] (E的最小距离)=无穷大,所以 dist[4]=11,path[4]=1
  • 第一轮算法两个邻边节点C、E有改变

b、第二轮算法执行

在这里插入图片描述

  • 如上图,因为dist[]中排出掉集合U中节点,最小值是5,也就是节点C,所以将C纳入到集合S中(圈中)。
  • 首先在dist[]数组中并在集合U中 最小值是节点C,既当前节点,其邻边有E和F,所以看是否要更新E和F。
    • 节点E:因为C的最小距离 dist[2](也就是C的最小距离)5+6(C到E的距离)=11 == dist[4](E的最小距离) = 11,所以不动
    • 节点F:因为F的最小距离 dist[2](也就是C的最小距离)5+4(C到F的距离)=9 < dist[5] (F的最小距离)=无穷大,所以 dist[5]=9,path[5]=2
  • 第二轮算法两个邻边节点仅有 F有改变

c、第三轮算法执行

在这里插入图片描述

  • 如上图,因为dist[]中排出掉集合U中节点,最小值是6,也就是节点D,所以将D纳入到集合S中(圈中)。
  • 首先在dist[]数组中并在集合U中 最小值是节点D,既当前节点,其邻边有C和F,所以看是否要更新C和F。
  • 节点C:因为C的最小距离 dist[3](也就是D的最小距离)6+2(D到C的距离)=8 > dist[2](C的最小距离) = 5 ,所以不动
  • 节点F:因为F的最小距离 dist[3](也就是D的最小距离)6+5(D到F的距离)=11 > dist[5] (F的最小距离)=9,所以不动
  • 第三轮算法两个邻边节点C、F都没有改变

d、第四轮算法执行

在这里插入图片描述

  • 如上图,因为dist[]中排出掉集合U中节点,最小值是9,也就是节点F,所以将F纳入到集合S中(圈中)。
  • 首先在dist[]数组中并在集合U中 最小值是节点F,既当前节点,其邻边有E和G,所以看是否要更新E和G 。
  • 节点E:因为E的最小距离 dist[5](也就是F的最小距离) 9 +1(F到E的距离)=10 < dist[4](E的最小距离) =11,所以 dist[4] = 10,path[4]=5
  • 节点G:因为G的最小距离 dist[5](也就是F的最小距离) 9 +8(F到G的距离)=17 < dist[6](G的最小距离) =无穷大,所以 dist[6]=17,path[6]=5
  • 第四轮算法两个邻边节点E、G都有改变

e、第五轮算法执行

在这里插入图片描述

  • 如上图,因为dist[]中排出掉集合U中节点,最小值是9,也就是节点F,所以将F纳入到集合S中(圈中)。
  • 首先在dist[]数组中并在集合U中 最小值是节点E,既当前节点,其邻边有G,所以看是否要更新G
  • 节点G:因为G的最小距离 dist[4](也就是E的最小距离) 10 +6(E到G的距离)=16 < dist[6](G的最小距离) =17,所以 dist[6]=16,path[6]=4
  • 第五轮算法邻边 节点G有改变

f、第六轮算法执行

在这里插入图片描述

  • 如上图,因为dist[]中排出掉集合U中节点,最小值是16,也就是节点G,所以将G纳入到集合S中(圈中)。
  • 首先在dist[]数组中并在集合U中 最小值是节点G,既当前节点,其没有邻边。
  • 第六轮算法邻边节点G没有改变
  • 到此算法遍历结束

4、java算法实现

给定矩阵表示的Graph结构。输入源点v0和终点v1。


二、多源最短路径

1、多源最短路径问题

  • 上面的Dijkstra 解决的是单源最短路径的问题,首先要给定 开始节点和终止结点,如果换了开始和终止节点,那就要每次都要重新跑一次。
  • 那就引出了多源最短路径问题:就是执行一次算法,求出每两个点之间的最短距离,这就是多源最短路径算法。这个算法代码略简单一些。
  • 思想只有一个:要算两个点之间的最短距离,就看有没有第三个点使得

2、Floyd初始化

首先已知的是:
给定 **邻接矩阵表示的图Graph。

a、参数

参数名解释
A[][]函数中的参数,需要返回,存储的是节点的前置节点。
path[][]存储的是每两点之间的所需距离。

b、参数初始化

参数名解释
A[][]就是图的赋值,从代码中可以看出,比较简单
path[][]默认都是-1.表示从A点到B点是直达的。

c、算法步骤

  1. 对于每个顶点v(体现在代码的第一层for循环),和任意一顶点(i,j)(体现代码的第二、三层循环),切 i!=j、v!=i、v!=j
  2. 如果A[i][j] > A[i][v] + A[]v[j],则将A[i][j] 更新为 A[i][v] + A[v][j] 的值,并且将path[i][j]改为v

3、Floyd算法详细步骤

4、java 算法实现

package com.feng.algorithm.self_learn.floyd.floyd1;/*** 学习视频:https://www.bilibili.com/video/BV1LE411R7CS*/
public class FloydAlgorithm {public static void main(String[] args) {int[][] graph = new int[4][4];int N = Short.MAX_VALUE;graph[0] = new int[]{0, 5, N, 7};graph[1] = new int[]{N, 0, 4, 2};graph[2] = new int[]{3, 3, 0, 2};graph[3] = new int[]{N, N, 1, 0};int[][] path = new int[4][4];int[][] A = Floyd.floyd(graph, path);int u = 1;int v = 0;Floyd.printPath(u, v, path);System.out.println();System.out.println(u + "->" + v +" shortest path is :" + A[u][v]);}
}
class Floyd {/*** 佛洛依德算法,给定邻接矩阵表示的图,* path[][]:存放路径中间的节点,如果是-1就是直达* A[][]:存放任意两个节点之间的距离* 举例:从1-0,从A得出距离是6,从path得出 1-3-2-0* @param graph* @param path*/static int[][] floyd(int[][] graph, int[][] path) {int n = graph.length;int v, i, j;int[][] A = new int[n][n];for (i = 0; i < n; i++) {for (j = 0; j < n; j++) {A[i][j] = graph[i][j];path[i][j] = -1;}}for (v = 0; v < n; v++) {for (i = 0; i < n; i++) {for (j = 0; j < n; j++) {if (A[i][j] > A[i][v] + A[v][j]) {A[i][j] = A[i][v] + A[v][j];path[i][j] = v;}}}}return A;}/*** 递归打印路径* @param u* @param v* @param path*/static void printPath(int u, int v, int[][] path) {if (path[u][v] == -1) { // 如果等于 -1 。说明就是直达的System.out.printf(u + "->" + v + " ");} else {int mid = path[u][v];printPath(u, mid, path);printPath(mid, v, path);}}
}

相关文章:

数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。

文章目录 前言一、单源最短路径1、单源最短路径问题2、Dijkstra 初始化a、参数b、初始化参数c、算法步骤 3、Dijkstra 算法详细步骤a、第一轮算法执行b、第二轮算法执行c、第三轮算法执行d、第四轮算法执行e、第五轮算法执行f、第六轮算法执行 4、java算法实现 二、多源最短路径…...

改进YOLO系列:6.添加ECA注意力机制

添加ECA注意力机制 1. ECA注意力机制论文2. ECA注意力机制原理3. ECA注意力机制的配置3.1common.py配置3.2yolo.py配置3.3yaml文件配置1. ECA注意力机制论文 论文题目:ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks 论文链接:ECA-N…...

软件测试知识点总结(一)

文章目录 前言一. 什么是软件测试二. 软件测试和软件调试的区别三. 软件测试和研发的区别四. 优秀的测试人员所应该具备的素质总结 前言 在现实生活中的很多场景下&#xff0c;我们都会进行测试。 比如买件衣服&#xff0c;我们需要看衣服是不是穿着好看&#xff0c;衣服材质如…...

持续集成与持续交付:现代软件测试的变革之路

引言 在数字化时代&#xff0c;软件开发的速度和复杂性都在不断增加。为了满足市场的需求&#xff0c;企业需要更快、更高效地交付高质量的软件产品。在这样的背景下&#xff0c;持续集成与持续交付&#xff08;CI/CD&#xff09;成为了软件开发和测试的核心实践。 软件开发的…...

深度学习基本理论下篇:(梯度下降/卷积/池化/归一化/AlexNet/归一化/Dropout/卷积核)、深度学习面试

深度学习基本理论上篇&#xff1a;&#xff08;MLP/激活函数/softmax/损失函数/梯度/梯度下降/学习率/反向传播&#xff09; 深度学习基本理论上篇&#xff1a;&#xff08;MLP/激活函数/softmax/损失函数/梯度/梯度下降/学习率/反向传播&#xff09;、深度学习面试_会害羞的杨…...

[Ubuntu 20.04] 通过udev规则修改网卡名称(例如eth0)

在 Ubuntu 20.04 操作系统中,默认情况下,网卡接口名称采用了一种较为复杂的命名方式(如 enp0s3、eth0 等)。然而,有时候我们可能更希望使用更简洁和易于识别的名称来标识不同的网络接口。那么如何在 Ubuntu 20.04 中修改网卡接口的名称,以满足个性化需求。 步骤一:查看当…...

Java“牵手”根据关键词搜索(分类搜索)lazada商品列表页面数据获取方法,lazadaAPI实现批量商品数据抓取示例

lazada商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取lazada商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问lazada商城的网页来获取商品详情信息。以下是两种常用方法的介…...

Java—实现多线程程序 | 入门

目录 一、前言 二、基本概念 进程 线程 三、Java多线程实现 java.lang.Thread类 获取线程名字及对象 获取main进程名 Thread currentThread() 四、线程优先级 设置优先级 一、前言 前期入门学习的代码中&#xff0c;全部都是单线的程序&#xff0c;也就是从头到尾…...

8.5 【C语言】指向函数的指针

8.5.1 什么是函数的指针 每次调用函数时都从该地址入口开始执行此段函数代码。函数名代表函数的起始地址。 8.5.2 用函数指针变量调用函数 例8.22 用函数求整数a和b中的大者 解题思路&#xff1a;在主函数调用max函数&#xff0c;除了可以通过函数名调用外&#xff0c;还可…...

C++实现字符串的逆置

目录 C和C的区别 【1】C对C的扩充 【2】C对C的兼容 第一个C程序 【1】hello world 【2】cout标准输出流对象 i&#xff09;介绍 ii&#xff09;运算 iii&#xff09;cout的使用 iv&#xff09;使用cout指定格式的输出 练习&#xff1a;1、输出斐波那契的前10项。 【3】…...

论Spring或Spring Boot的花式扩展

文章目录 引言扩展点讲述花式扩展之自动配置类花式扩展之实现接口实现方式样例 花式扩展之自定义starterImport方式SpringFactories方式 总结鸣谢 引言 Spring Boot是一个高度可定制的框架&#xff0c;旨在帮助开发者快速创建、配置和管理他们的应用程序 扩展点讲述 Spring Bo…...

如何评估分类模型的好坏

如何评估分类模型的好坏 评估分类预测模型的质量&#xff0c;常用一个矩阵、三条曲线和六个指标。 一个矩阵&#xff1a;混淆矩阵&#xff1b;三条曲线&#xff1a;ROC曲线、PR曲线、KS曲线&#xff1b;六个指标&#xff1a;正确率Acc、查全率R、查准率P、F值、AUC、BEP值、KS…...

● 84.柱状图中最大的矩形

84.柱状图中最大的矩形 class Solution { public:int largestRectangleArea(vector<int>& heights) {stack<int>st;heights.insert(heights.begin(),0);heights.push_back(0);st.push(0);int res0;for(int i1;i<heights.size();i){while(heights[i]<heig…...

未检查的转换: ‘java.lang.Object‘ 转换为 ‘java.util.List

fastjson方式 Object object ... // 获取待转换的objectList<WbsCategory> list JSON.parseObject(JSON.toJSONString(object), new TypeReference<List<WbsCategory>>() {}); 在这个示例中&#xff0c;我们使用JSON.toJSONString()将object对象转换…...

【C语言】使用C语言,实现九九乘法表(另附Python、Java、JavaScript实现方式)

文章目录 1. C语言实现1.1 思路1.2 代码实现 3.其他语言实现3.1 Python实现3.2 Java实现3.3 JavaScript实现 1. C语言实现 1.1 思路 九九乘法表图示&#xff1a; 思路如下&#xff1a;定义两层for循环即可实现九九乘法表 一共有9层&#xff0c;所以要定义一个变量i&#xff…...

[机缘参悟-102] :IT人 - 管理的本质?管理人与从事技术的本质区别?人性、冰山模型、需求层次模型

感悟&#xff1a; 管理的本质是&#xff1a;学习各种管理理论、方法、技能&#xff0c;克服自身的人性缺点、预防他人人性的恶点、利用他人的人性特点拿到结果&#xff0c;从而完成组织、管理者的上司、管理者自身、管理者下属的目标。管理中的问题&#xff0c;80%以上都人性问…...

[论文阅读笔记26]Tracking Everything Everywhere All at Once

论文地址: 论文 代码地址: 代码 这是一篇效果极好的像素级跟踪的文章, 发表在ICCV2023, 可以非常好的应对遮挡等情形, 其根本的方法在于将2D点投影到一个伪3D(quasi-3D)空间, 然后再映射回去, 就可以在其他帧中得到稳定跟踪. 这篇文章的方法不是很好理解, 代码也刚开源, 做一…...

【Java 动态数据统计图】前后端对接数据格式(Map返回数组格式数据)六(120)

说明&#xff1a; 前端使用&#xff1a;vue3.0 前后端对接数据格式&#xff1a;无非就是前端把后端返回的数据处理为自己想要的格式&#xff0c;或者&#xff0c;后端给前端处理好想要的格式&#xff1b; 针对前后端的柱状图&#xff0c;趋势图等数据对接&#xff0c;前端一般需…...

❤ 给自己的mac系统上安装java环境

❤ 给自己的mac系统上安装java环境 &#x1f353; 作为前端工程师如何给自己的mac系统上安装java环境 &#x1f34e; 最近因为自己的一些项目需求&#xff0c;mac电脑上需要安装一些后台的java环境&#xff0c;用来跑后台的java程序&#xff0c;于是从一个前端工程师的角度安…...

Java-匿名类

介绍 匿名类是指没有名字的类&#xff0c;它对一个给定的类进行拓展&#xff0c;或者实现一个给定的接口。使用匿名类可以使得代码更加简洁、紧凑、模块程度更高。 实现方式及语法 匿名类有两种实现方式 继承一个类&#xff0c;重写其方法实现一个接口&#xff08;可以是多…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

【51单片机】4. 模块化编程与LCD1602Debug

1. 什么是模块化编程 传统编程会将所有函数放在main.c中&#xff0c;如果使用的模块多&#xff0c;一个文件内会有很多代码&#xff0c;不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里&#xff0c;在.h文件里提供外部可调用函数声明&#xff0c;其他.c文…...