[图的搜索]5.图解狄克斯特拉算法及其代码演示

news2025/1/10 16:13:31

狄克斯特拉算法

与前面提到的贝尔曼-福特算法类似,狄克斯特拉(Dijkstra)算法也是求解最短路径问题的算法,使用它可以求得从起点到终点的路径中权重总和最小的那条路径路径。

图解

01

这里我们设A为起点、G为终点,来讲解狄克斯特拉算法。


02

首先设置各个顶点的初始权重:起点为0,其他顶点为无穷大(∞)。


03

从起点出发。


04

寻找可以从目前所在的顶点直达且尚未被搜索过的顶点,此处为顶点B和顶点C,将它们设为下一步的候补顶点。


05

计算各个候补顶点的权重。计算方法是“目前所在顶点的权重+目前所在顶点到候补顶点的权重”。比如起点A的权重是0,那么顶点B的权重就是0+2=2。用同样的方法计算顶点C,结果就是0+5=5。

06

如果计算结果小于候补顶点的值,就更新这个值。顶点B和顶点C现在的权重都是无穷大,大于计算结果,所以更新这两个顶点的值。

07

从候补顶点中选出权重最小的顶点。此处B的权重最小,那么路径A-B就是从起点A到顶点B的最短路径。因为如果要走别的路径,那么必定会经过顶点C,其权重也就必定会高于A-B这条路径。

08

确定了最短路径,移动到顶点B。

09

将可以从顶点B直达的顶点设为新的候补顶点,于是顶点D和顶点E也成为了候补。目前有三个候补顶点C、D、E。

10

用相同的方法计算各个候补顶点的权重。从B到C的权重为2+6=8,比C当前的权重5大,因此不更新这个值。

11

更新了剩下的顶点D和E。


12


从候补顶点中选出权重最小的顶点。此处D的权重最小,那么路径A-B-D就是从起点A到顶点D的最短路径。


13

A-B-D这条路径是通过逐步从候补顶点中选择权重最小的顶点来得到的,所以如果经过其他顶点到达D,其权重必定会大于这条路径。


14

要重复执行同样的操作直到到达终点G为止。移动到顶点D后算出了E的权重,然而并不需要更新它(因为3+4=7)。现在,两个候补顶点C和E的权重都为5,所以选择哪一个都可以。


15

此处我们选择了C,于是起点A到顶点C的最短路径便确定了。


16

移动到C后,顶点F成为了新的候补顶点,且F的权重被更新为13。此时的候补顶点中,E为5、F为13,所以……


17

我们选择了权重更小的E,起点A到顶点E的最短路径也就确定了下来。


18

移动到E。G成了新的候补顶点,其权重也被更新为14。此时的候补顶点中,F为13、G为14,所以选择了F。由此,起点A到顶点F的最短路径也就确定了下来。


19
        
移动到F。顶点G的权重计算结果为13+7=20,比现在的值14要大,因此不更新它。由于候补顶点只剩G了,所以选择G,并确定了起点A到顶点G的最短路径。


20

到达终点G,搜索结束。


21

用粗线条标注的就是从起点A到终点G的最短路径。


解说
比起需要对所有的边都重复计算权重和更新权重的贝尔曼-福特算法,狄克斯特拉算法多了一步选择顶点的操作,这使得它在求最短路径上更为高效。
将图的顶点数设为n、边数设为m,那么如果事先不进行任何处理,该算法的时间复杂度就是O(n2)。不过,如果对数据结构进行优化,那么时间复杂度就会变为O(m+nlogn)。

Dijkstra算法通过不断选择当前离起始节点最近的节点,并更新与其相邻节点的距离,逐步求解从起始节点到其余各节点的最短路径。

补充说明

狄克斯特拉算法和贝尔曼-福特算法一样,也能在有向图中求解最短路径问题。
但是如果图中含有负数权重,狄克斯特拉算法可能会无法得出正确答案,这一点和贝尔曼-福特算法有所不同。比如右边这个图中,A-C-B-G为正确的最短路径,权重为4+(-3)+1=2。
然而,如果用狄克斯特拉算法来求解,得到的却是下面这样的最短路径树。从起点A到终点G的最短路径为A-B-G,权重为3。这个答案显然是错误的。

如果闭环中有负数权重,就不存在最短路径。贝尔曼-福特算法可以直接认定不存在最短路径,但在狄克斯特拉算法中,即便不存在最短路径,它也会算出一个错误的最短路径出来。因此,有负数权重时不能使用狄克斯特拉算法。
总的来说,就是不存在负数权重时,更适合使用效率较高的狄克斯特拉算法,而存在负数权重时,即便较为耗时,也应该使用可以得到正确答案的贝尔曼-福特算法。
 

一句话总结:

Dijkstra算法通过不断选择当前离起始节点最近的节点,并更新与其相邻节点的距离,逐步求解从起始节点到其余各节点的最短路径。

演示: 

import heapq

# Dijkstra算法函数,计算起始节点到图中各节点的最短距离
def dijkstra(graph, start):
    # 初始化距离字典,所有节点距离起始节点为无穷大
    distances = {node: float('inf') for node in graph}
    distances[start] = 0  # 起始节点到自身距离为0
    pq = [(0, start)]  # 优先队列,存储节点的距离和节点名称
    
    while pq:  # 当优先队列不为空时循环
        current_dist, current_node = heapq.heappop(pq)  # 弹出当前距禧最小的节点和距离
        
        if current_dist > distances[current_node]:
            continue  # 如果当前节点已经处理过,则跳过
        
        # 遍历当前节点的邻居节点
        for neighbor, weight in graph[current_node].items():
            distance = current_dist + weight  # 计算邻居节点的新距离
            
            # 如果新距离小于已知距离,则更新距离并加入优先队列
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(pq, (distance, neighbor))
    
    return distances  # 返回起始节点到各节点的最短距离字典

# 示例图
graph = {
    'A': {'B': 2, 'C': 5},
    'B': {'A': 2, 'C': 6, 'D': 1, 'E': 3},
    'C': {'A': 5, 'B': 6, 'F': 8},
    'D': {'B': 1, 'E': 4},
    'E': {'D': 4, 'B': 3, 'G': 9},
    'F': {'C': 8, 'G': 7},
    'G': {'F': 7, 'E': 9},
}

start_node = 'A'

# 调用Dijkstra算法函数并输出结果
result = dijkstra(graph, start_node)
print(result)

结果:

{'A': 0, 'B': 2, 'C': 5, 'D': 3, 'E': 5, 'F': 13, 'G': 14}

———————————————————————————————————————————

文章来源:书籍《我的第一本算法书》

书籍链接:

我的第一本算法书 (豆瓣) (douban.com)

作者:宫崎修一 石田保辉

出版社:人民邮电出版社

ISBN:9787115495242

本篇文章仅用于学习和研究目的,不会用于任何商业用途。引用书籍《我的第一本算法书》的内容旨在分享知识和启发思考,尊重原著作者宫崎修一和石田保辉的知识产权。如有侵权或者版权纠纷,请及时联系作者。
———————————————————————————————————————————

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

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

相关文章

“揭秘乐园通行证:Spring JWT的魔法之旅

嗨&#xff0c;我将带你深入了解如何利用JWT打造一个既安全又高效的网络乐园。从基础概念到实战技巧&#xff0c;再到安全策略&#xff0c;每一步都充满惊喜。你将学会如何为乐园设置无状态的门票系统&#xff0c;如何通过RBAC和ABAC确保游客安全&#xff0c;以及如何在微服务架…

统计信号处理-匹配滤波器实现与验证(matlab仿真)

什么是匹配滤波器 匹配滤波器是一种信号处理技术&#xff0c;它用于从噪声中提取信号&#xff0c;特别是在信号与噪声比率较低的情况下。匹配滤波器之所以存在&#xff0c;是因为它在信号检测和估计方面具有几个关键的优势&#xff1a; 最大化信噪比&#xff1a;匹配滤波器设计…

数字化校园建设让学习更加广阔

校园构建数字化校园的亮点是什么&#xff1f;校园以智能服务、才智办理、数字讲堂为中心内容的智慧校园建造&#xff0c;不只使师生作业和日子更高效&#xff0c;并且使他们有更多的时刻投入到智能教育和智能学习中去&#xff0c;进步教育质量&#xff0c;使学生走出校门时紧跟…

项目管理主要文档介绍

1、商业论证&#xff1a;一般由项目发起人创建&#xff0c;用于论证项目是否对组织有财务方面的收益。商业论证创建于项日开始之前&#xff0c;用于判断项目是否需要被开展。 2、项目章程&#xff1a;一般由项日经理创建,并由发起入和关键相关力提供输人&#xff0c;最后经项目…

MATLAB函数模块光显示zeros/poles怎么办?

出现下面这种图了怎么办&#xff1f;是做错了吗&#xff1f; 这种图就是它显示不完整了&#xff0c;把它拉大点就可以完全显示了。

【机器学习】深入探索机器学习:利用机器学习探索股票价格预测的新路径

❀机器学习 &#x1f4d2;1. 引言&#x1f4d2;2. 多种机器学习算法的应用&#x1f4d2;3. 机器学习在股票价格预测中的应用现状&#x1f389;数据收集与预处理&#x1f389;模型构建与训练&#x1f308;模型评估与预测&#x1f31e;模型评估&#x1f319;模型预测⭐注意事项 &…

检定记录内容解析:非红外二氧化硫气体检测仪的维护与验证

在工业生产与环境保护中&#xff0c;二氧化硫作为一种常见的有害气体&#xff0c;其浓度的监测和控制显得尤为重要。 非红外二氧化硫气体检测仪以其独特的检测原理和高灵敏度&#xff0c;在二氧化硫监测领域发挥着不可或缺的作用。 在这篇文章中&#xff0c;佰德将详细介绍非…

【原创】springboot+mysql校园通讯录管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

MongoDB CRUD操作:插入文档

MongoDB CRUD操作&#xff1a;插入文档 文章目录 MongoDB CRUD操作&#xff1a;插入文档使用MongoDB Atlas UI插入文档插入单个文档插入多个文档插入行为自动创建集合_id字段原子性写确认 在MongoDB中插入文档的集中方式&#xff1a; 使用编程语言提供的驱动程序&#xff0c;在…

【第七节】C++的STL基本使用

目录 前言 一、STL简介 1.1 STL基本概念 1.2 STL六大组件 1.3 STL优点 二、STL三大组件 2.1 容器 2.2 算法 2.3 迭代器 三、STL常见的容器 3.1 string容器 3.1.1 string容器基本概念 3.1.2 string容器的常用操作 3.1.2.1 string 构造函数 3.1.2.2 string 基本赋…

U盘格式化怎么操作?快来学这4种法

U盘格式化怎么操作&#xff1f;在计算机领域中&#xff0c;格式化通常指对存储设备&#xff08;如硬盘、U盘&#xff09;进行格式化操作&#xff0c;清空其中的数据并重新建立文件系统&#xff0c;以便进行数据存储和管理。 U盘格式化一共有哪些方法&#xff1f;在格式化U盘之…

SJ701-II安全帽耐冲击穿刺测试仪

一、主要用途 主要用于安全帽耐冲击性能和耐穿刺性能试验。 二、仪器特征 整机创新全新结构&#xff0c;并获得国家专利&#xff08;专利号201420182139.8&#xff09; 1、整机结构&#xff1a;首创采用欧标型材组装成型&#xff0c;内藏式线路折叠式结构。结构美观耐用&…

07.爬虫---使用session发送请求

07.使用session发送请求 1.目标网站2.代码实现 1.目标网站 我们以这个网站作为目标网站 http://www.360doc.com/ 注册用户 注册后从登录界面获取到这些信息 2.代码实现 import requestssession requests.Session() url http://www.360doc.com/ajax/login/login.ashx u…

基于SSM框架的手机商城项目

后端: 订单管理 客户管理&#xff1a; 商品管理 类目管理 前端&#xff1a; 首页&#xff1a;

windows 在cmd 使用cd命令无法进入指定目录解决方法

目录预览 一、问题描述二、原因分析三、解决方案四、参考链接 一、问题描述 使用cmd命令想要快速进入某个目录&#xff0c;发现没有跳转&#xff0c;如下&#xff1a; 二、原因分析 cmd 切换目录跨磁盘的话&#xff0c;需要先进行磁盘的转换&#xff0c;也就是要进入到另外一…

码蹄集部分题目(2024OJ赛17期;二分+差分+ST表+单调队列+单调栈)

1&#x1f40b;&#x1f40b;小码哥处理订单&#xff08;钻石&#xff1b;二分差分&#xff09; 时间限制&#xff1a;1秒 占用内存&#xff1a;128M &#x1f41f;题目描述 &#x1f41f;题目思路 【码蹄集进阶塔全题解07】算法基础&#xff1a;二分 MT2070 – MT2079_哔哩…

Kafka系列之高频面试题

基础 简介 特点&#xff1a; 高吞吐、低延迟&#xff1a;kafka每秒可以处理几十万条消息&#xff0c;延迟最低只有几毫秒&#xff0c;每个Topic可以分多个Partition&#xff0c;Consumer Group对Partition进行Consumer操作可扩展性&#xff1a;Kafka集群支持热扩展持久性、可…

JavaScript解构赋值

一、数组解构 以上要么不好记忆&#xff0c;要么书写麻烦&#xff0c;此时可以使用解构赋值的方法让代码更简洁。 数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法。 基本语法&#xff1a; 1、赋值运算符左侧的[]用于批量声明变量&#xff0c;右侧数组的单元值将…

库卡机械手伺服电机过压报警维修措施

一、KUKA机械手伺服电机过压报警原因库卡机器人电机过压报警通常是由于电机供电电压过高、电机绕组短路、电机负载过大等原因引起的。当电机供电电压超过额定电压一定范围&#xff0c;或者电机绕组出现短路故障&#xff0c;或者电机负载过大导致电流过大时&#xff0c;电机电流…

MoeCTF 2022 usb

直接找 URB的第一个输入协议 我们需要提取的数据 HID Data 提取过滤器 tshark -r usb.pcapng -Y "usb.src\"2.2.1\"" -T json >1.json 拿 usbhid.data 字段 tshark -r usb.pcapng -Y "usb.src\"2.2.1\"" -T json -e usbhid.data …