Dijkstra求最短路篇二(全网最详细讲解两种方法,适合小白)(python,其他语言也适用)

前言:

Dijkstra算法博客讲解分为两篇讲解,这两篇博客对所有有难点的问题都会讲解,小白也能很好理解。看完这两篇博客后保证收获满满。

第一篇博客讲解朴素Dijkstra算法Dijkstra求最短路篇一(全网最详细讲解两种方法,适合小白)(python,其他语言也适用),本篇博客讲解堆优化Dijkstra算法,两中算法思路大体相同,但时间复杂度有所区别。

  • 朴素Dijkstra算法:时间复杂度 O ( n 2 ) O(n^2) O(n2)
  • 堆优化Dijkstra算法:时间复杂度 O ( m l o g n ) O(mlogn) O(mlogn)

两篇博客给出的题目内容一样,只有数据规模不一样。

题目:

题目链接:
850. Dijkstra求最短路 II

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为非负值。请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1。

输入格式
第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。

输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。
如果路径不存在,则输出 −1。

数据范围(两题不同处)
1 ≤ n , m ≤ 1.5 × 1 0 5 1≤n,m≤1.5×10^5 1n,m1.5×105,
图中涉及边长均不小于 0,且不超过 10000。
数据保证:如果最短路存在,则最短路的长度不超过 1 0 9 10^9 109

输入样例:

3 3
1 2 2
2 3 1
1 3 4

输出样例:

3

思路:

算法分析:
在这里插入图片描述

依旧是Dijkstra算法求解,不同的是本题需要降低时间复杂度。

对朴素Dijkstra算法时间复杂度分析可知:

  • 寻找路径最短的点: O ( n 2 ) O(n^2) O(n2)
  • 加入集合S: O ( n ) O(n) O(n)
  • 更新距离: O ( m ) O(m) O(m)
  • 所以总的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

所以我们需要对寻找路径最短的点进行改变,如何降低找最短距离的点的时间复杂度呢?
这里可以使用最小堆进行优化(也就是优先队列),对优先队列不太熟悉的可以看看优先队列这篇博客,其他博主写的很详细这里我就不介绍了。

进行优化后时间复杂度分析如下:

  • 寻找路径最短的点: O ( n ) O(n) O(n)
  • 加入集合S: O ( n ) O(n) O(n)
  • 更新距离: O ( m l o g n ) O(mlogn) O(mlogn)

堆的数据结构大家接触的可能有点少,python中有专门的库函数可以直接使用,其他语言也有类似的库函数可以使用。

构造邻接表:

首先对数据进行存储,图的存储有两种方式,一种是邻接表,一种是邻接矩阵。题目中的数据规模用邻接表存储(本题数据规模是稀疏图)。

为什么要用邻接表去存贮,而不是邻接矩阵?

我们采用邻接矩阵还是采用邻接表来表示图,需要判断一个图是稀疏图还是稠密图。稠密图指的是边的条数|E|接近于|V|²,稀疏图是指边的条数|E|远小于于|V|²(数量级差很多)。本题是稠密图,显然稠密图用邻接矩阵存储比较节省空间,反之用邻接表存储。

邻接表存储就不需要注意重边和自环了,因为算法会自动算出最优解

邻接矩阵存储代码如下:

n, m = map(int, input().split())  # 图的节点个数和边数
#  构建邻接表 
num = [[] for i in range(n + 1)]
for _ in range(m):a, b, c = map(int, input().split())num[a].append((b, c))  # 无需考虑重边和自环

以题目实例为例,打印num数组

[[], [(2, 2), (3, 4)], [(3, 1)], []]

邻接表构建完成之后就要进行Dijkstra算法,这里直接给出代码,用详细代码给大家进行讲解。整体思路跟朴素Dijkstra算法大致相同

代码及详细注释:

import heapqn, m = map(int, input().split())  # 图的节点个数和边数
#  构建邻接表 
num = [[] for i in range(n + 1)]
for _ in range(m):a, b, c = map(int, input().split())num[a].append((b, c))  # 无需考虑重边和自环
dist = [float("inf") for _ in range(n + 1)]  # float("inf")在python中是无限大的意思
dist[1] = 0  # 源点到源点的距离为置为 0
state = [False for i in range(n + 1)]  # state 用于记录该点的最短距离是否已经确定def dijstra():# 这里heap中为什么要存两个值呢,首先小根堆是根据距离来排的,所以有一个变量要是距离,# 其次在从堆中拿出来的时候要知道知道这个点是哪个点,不然怎么更新邻接点呢?所以第二个变量要存点。heap = [(0, 1)]  # 首先放入距离0和点1,这个顺序不能倒,这里显然要根据距离排序while heap:distance, i = heapq.heappop(heap)  # 这里是取出最下距离和对应的点,最小堆自动取出最小值if state[i]:  # 如果该点最短距离已经确定,跳过下面操作continuestate[i] = True  # 标记该点距离确定for j, d in num[i]:  # 循环遍历找点i所能到的点和其距离if dist[j] > distance + d:  # 如果原本点j到源点的距离大于后续计算出来的值dist[j] = distance + d  # 更新heapq.heappush(heap, (dist[j], j))  # 该点距离和点加入到最小堆中# 判断最后一个点的最短距离是否找到,如果为无穷大,则表示未找到,返回-1,否则返回最短距离dist[-1]if dist[n] == float("inf"):return -1else:return dist[n]print(dijstra())

朴素Dijkstra算法大家理解好了本算法也很好理解,操作都是一样,只是在寻找路径最短的点时用了最小堆操作。这里就不拿实例带大家过了,如果略微有点懵,大家可以自己拿实例数据过一遍。

本题主要对 Python 中的 heapq 库进行简略讲解。

import heapqheap = []
heapq.heappush(heap, (1, 2))
heapq.heappush(heap, (1, 3))
heapq.heappush(heap, (2, 1))
heapq.heappush(heap, (2, 0))
heapq.heappush(heap, (0, 2))
heapq.heappush(heap, (0, 0))print("初始状态", heap)
print("删除的元素", heapq.heappop(heap))
print("删除后状态", heap)

运行结果:

初始状态 [(0, 0), (1, 2), (0, 2), (2, 0), (1, 3), (2, 1)]
删除的元素 (0, 0)
删除后状态 [(0, 2), (1, 2), (2, 1), (2, 0), (1, 3)]
  • heapq.heappush((heap, (1, 2)):把元素(1,2)加入到堆 heap中(每次加入后都是最小堆的构建形式)。
  • heapq.heappop(heap):弹出堆顶元素(最小堆的堆顶就是最小元素)。

总结:

堆优化版dijkstra适合稀疏图

思路:

堆优化版的dijkstra是对朴素版dijkstra进行了优化,在朴素版dijkstra中时间复杂度最高的寻找距离
最短的点O(n^2)可以使用最小堆优化。

  1. 一号点的距离初始化为零,其他点初始化成无穷大。
  2. 将一号点放入堆中。
  3. 不断循环,直到堆空。每一次循环中执行的操作为:
    弹出堆顶(与朴素版diijkstra找到S外距离最短的点相同,并标记该点的最短路径已经确定)。
    用该点更新临界点的距离,若更新成功就加入到堆中。

时间复杂度分析

  • 寻找路径最短的点: O ( n ) O(n) O(n)
  • 加入集合S: O ( n ) O(n) O(n)
  • 更新距离: O ( m l o g n ) O(mlogn) O(mlogn)

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

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

相关文章

计网ppt标黄知识点整理第(2)章节——谢希仁版本、期末复习自用

物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流,而不是指具体的传输媒体。4 个特性: 机械特性:指明接口所用接线器的形状和尺寸、引线数目和排列、固定和锁定装置等。 电气特性:指明在接口电缆的各条线上出现…

基于Springboot驾校预约平台小程序的设计与实现(源码+数据库+文档)

一.项目介绍 系统角色:管理员、教练、学员 小程序(仅限于学员注册、登录): 查看管理员发布的公告信息 查看管理员发布的驾校信息 查看所有教练信息、预约(需教练审核)、评论、收藏喜欢的教练 查看管理员发布的考试信息、预约考试(需管理…

2024年东北师范CCPC

文章目录 A.Paper WateringB.nIM gAMEE.Checksum A.Paper Watering 思路:题目说有平方和开方两种操作,如果这个数是平方数,那么它开方之后就只能开方,如果平方的话就重复了,反之就有开方和平方两种操作。 代码如下 //…

为了方便看公众号文章,我搭建了个博客,在线看公众号所有历史文章,想看哪天的文章一秒就能找到

公众号没有个网页版的文章列表,只能在电脑和手机客户端看,想看之前的历史文章只能一直往下拉,想找某篇文章非常费劲。 为了方便看公众号文章,我搭建了个博客,博客地址https://sushengbuhuo.github.io/blog &#xf…

通过 SFP 接口实现千兆光纤以太网通信1

基于米联客ARTIX-7 系列开发板及其开发手册。 总体实现框图如下: SFP 接口 SFP 信号定义如下图所示。 Tri Mode Ethernet MAC 设置 由于使用千兆通讯,因此将速率设为 1Gbps。如下图所示。 首先,由于该 IP 需要与 IP 核 1G/2.5G Ethernet …

基于IoTDB 平台的学习和研究

Apache IoTDB(物联网数据库)是一个针对物联网领域的高性能原生数据库,适用于数据管理和分析,并可在边缘计算和云端部署。由于它轻量级的架构、高性能和丰富的功能集,以及与Apache Hadoop、Spark和Flink的深度集成&…

数据管理知识体系必知的14张语境关系图

近期对数据管理知识体系中的语境关系图进行了整体学习梳理,总共有14张图,具体如下,供大家参考。应该说语境关系图和环境因素六边形图是各有侧重、互为补充关系。语境关系图是环境因素六边形图的细化,描述了每个知识领域中的细节,相当于数据管理的微观视角, 包括与人员、 …

kali中切换python版本

kali中切换python版本 在日常使用的过程中,可以通过一些工具来做打靶环境,或者工具的启动,都和python关联,而有时存在工具安装,或者运行的时候出现报错,这时候极大可能是因为我们本地的kali中python的版本不…

Android Studio | 小白如何运行别人的安卓项目

目录 Step1:正确地打开项目 Step2:AS 同步时报错 Step3:同步完成后启动 Step4:启动成功 说明:本文简称 Android Studio 为 AS Step1:正确地打开项目 重点:确认好项目的根目录是哪个目录&am…

进程与线程(三)

进程与线程(三) 进程间通信传统间的进程间通信机制无名管道无名管道的特征无名管道的创建父子进程通信测试管道的大小管道读写易出现的问题 有名管道创建有名管道有名管道的写端代码有名管道的读端代码 信号信号的特征产生信号硬件来源软件来源发送信号的…

【第1章】SpringBoot实战篇之注册接口

文章目录 前言一、代码部分1. User2.UserMapper13. UserSerivce4. UserController15. Result 二、测试1.注册2.再次注册 总结 前言 下面介绍用户注册接口。 一、代码部分 1. User package org.example.springboot3.bigevent.entity;import com.baomidou.mybatisplus.annotat…

开发板uboot与virtualbox虚拟机、windows11网络互通

环境:virtualbox中ubuntu22.04.4,开发板通过网线再经过拓展坞usb网卡跟windows11连接。连接如下: 1、关闭windows防火墙(重要) 2、先在VirtualBox的工具选项创建两个网络【仅主机(Host-Only)网络】和【NAT网络】 仅主机(Host-Only)网络的ip:…

Linux下Qt Creator无法输入中文(已解决)

1. 首先确保安装了搜狗输入法,且能正常运行。 2.克隆源码到本地。 git clone https://gitcode.com/fcitx/fcitx-qt5.git 3.检查Qt Creator版本,如下图所示,为基于Qt6的。 4. 进入源码目录,建立build文件夹,修改CMak…

css动态导航栏鼠标悬停特效

charset "utf-8"; /*科e互联特效基本框架CSS*/ body, ul, dl, dd, dt, ol, li, p, h1, h2, h3, h4, h5, h6, textarea, form, select, fieldset, table, td, div, input {margin:0;padding:0;-webkit-text-size-adjust: none} h1, h2, h3, h4, h5, h6{font-size:12px…

8、资源操作 Resource

目录 8.1、Spring Resources概述补充:什么是 low-level 资源?1. 文件系统资源2. 类路径资源3. URL资源4. 内嵌资源5. InputStream资源6. ServletContext资源示例代码结论 8.2、Resource接口8.3、Resource的实现类8.3.1、UrlResource访问网络资源1&#x…

LIO-EKF: 运行数据UrbanNav与mid360设备详细教程

一、代码连接 代码下载连接: YibinWu/LIO-EKF: Maybe the simplest LiDAR-inertial odometry that one can have. (github.com) 编译步骤: cd srcgit clone gitgithub.com:YibinWu/LIO-EKF.gitcatkin_makesource devel/setup.bash 运行步骤: …

java并发处理机制

在Java中,并发处理机制主要是通过线程来实现的。Java提供了丰富的类和接口来支持多线程编程,主要集中在 java.util.concurrent 包中。以下是一些关键的并发处理机制: 1.线程创建:可以通过继承 Thread 类或实现 Runnable 接口来创建…

公园【百度之星】/图论+dijkstra

公园 图论dijkstra #include<bits/stdc.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pii; vector<ll> v[40005]; //a、b、c分别是小度、度度熊、终点到各个点的最短距离 ll a[40005],b[40005],c[40005],dist[40005],st[40005]; void…

java 远程调试

1.远程启动时 jdk1.8-32\jre\bin\java.exe -Dfile.encodingUTF-8 -Djava.library.pathlib -agentlib:jdwptransportdt_socket,servery,suspendn,address5005 -jar local-com.yuetai.service-0.0.1-SNAPSHOT.jar --spring.config.locationapplication.yml 2.本地调试项目连接远…

JCR一区级 | Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多特征分类预测

JCR一区级 | Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多特征分类预测 目录 JCR一区级 | Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多特征分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多…