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

狄克斯特拉算法

与前面提到的贝尔曼-福特算法类似,狄克斯特拉(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.mfbz.cn/a/664365.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

论文笔记:Image Anaimation经典论文-运动关键点模型(Monkey-Net)

Monkey-Net&#xff08;MOviNg KEYpoints&#xff09; paper: https://arxiv.org/pdf/1812.08861, CVPR 2019 code: https://github.com/AliaksandrSiarohin/monkey-net/tree/master 相关工作 视频生成演变过程&#xff1a; spatio-temporal network: 如基于GAN网络的生成模…

探索重庆耶非凡科技:揭秘其背后的技术实力与市场布局

重庆耶非凡科技有限公司&#xff0c;作为重庆当地一家知名的综合性服务型企业&#xff0c;近年来在多个领域取得了显著的成绩。其业务范围广泛&#xff0c;不仅涵盖了传统的行业服务&#xff0c;还积极探索并实践了一系列创新项目&#xff0c;其中最为引人注目的便是选品师项目…

Linux服务器搭建http服务,添加DNS域名解析

效果如下&#xff1a;搭建自己的网站&#xff0c;添加域名解析服务后&#xff0c;外网可访问 1.搭建http服务器&#xff0c;可通过局域网下的ip访问 2.DNS域名解析服务&#xff0c;链接ip到公网&#xff0c;外网可以通过对应的域名访问 1.安装httpd yum install httpd #根据提示…

记录Win11安装打印机驱动过程

1. 首先下载打印机对应型号的驱动 可以从这里下载&#xff1a;打印机驱动,打印机驱动下载 - 打印机驱动网 2. 下载 3. 打开控制面板-->设备和打印机 找到目标打印机添加设备即可 新增打印纸张尺寸

2024年在抖音赚钱,可以不用直播,拍短视频了!

短视频经济发展的越来越快&#xff0c;不少人靠着这次风口&#xff0c;在抖音做直播&#xff0c;拍视频赚到了不少钱。 很多人普通人靠着抖音的流量&#xff0c;一夜之间暴富的案例数不胜数。 像“郭有才”“王妈”就是个明晃晃的例子。 但是很多人都说现在这样的案例越来越…

上海晋名室外危废暂存柜助力谐波传动减速器行业危废品安全储存

近日又有一台 SAVEST 室外危废暂存柜项目成功验收交付使用&#xff0c;此次项目主要用于谐波传动减速器行业危废品安全储存。 用户单位成立于1994年&#xff0c;是我国专业从事谐波传动减速器技术设计、开发、生产、销售、服务的高新技术实业公司。在日常工作运营中涉及到危废…

10.Redis之set类型

谈到一个术语,这个术语很可能有多种含义~~ 1.Set 1) 集合. 2)设置 (和 get 相对应) 集合就是把一些有关联的数据放到一起~~ 1.集合中的元素是无序的! 【此处说的无序和 前面list这里的有序 是对应的, 有序: 顺序很重要. 变换一下顺序, 就是不同的 list 了 无序: 顺序不…

嵌入式几种常用的滤波算法

几种常用的滤波算法 一.修改记录 2024-01-26修改 1.中值滤波负数时失效&#xff0c;补充一下。 二.修改记录 1、限幅消抖滤波法&#xff08;又称程序判断滤波法&#xff09; 2、中位值滤波法 3、算术平均滤波法 4.一阶滞后滤波法 5.加权递推平均滤波法 6.消抖滤波法 …

轻兔推荐 —— MyIP

via&#xff1a;轻兔推荐 简介 一个功能全面的IP工具箱。轻松检查你的 IP&#xff0c;IP 地理位置&#xff0c;检查DNS泄漏&#xff0c;检查 WebRTC 连接&#xff0c;速度测试&#xff0c;ping 测试&#xff0c;MTR测试&#xff0c;检查网站可用性&#xff0c;查询 Whois 信…

Linux基础指令及其作用之系统信息和管理

系统信息和管理 ps ps 命令用于显示当前系统的进程信息。它是 Unix 和类 Unix 操作系统中的一个重要工具&#xff0c;可以用于监控和管理系统进程。以下是 ps 命令的详细用法和常见选项&#xff1a; ps [选项]常用选项![在这里插入图片描述](https://img-blog.csdnimg.cn/di…

Apose.Words 常用对象详解

系列文章目录 文章目录 系列文章目录前言一、基础对象1. moveToBookmark 前言 本文介绍 Apose.Words 的常用对象的含义及使用方法。 一、基础对象 1. moveToBookmark 将指针移动到书签位置。 moveToBookmark(String bookmarkName, boolean isStart, boolean isAfter) book…

博客增长与数据分析:不可不知的 6 大策略

CSDN 的朋友你们好&#xff0c;我是何未来&#xff0c;一个热爱编程和写作的计算机本科生&#xff0c;今天给大家带来专栏【程序员博主教程&#xff08;完全指南&#xff09;】的第 11 篇文章“分析和追踪博客表现”。本篇文章为你揭示了如何通过数据洞察来优化你的技术博客&am…

Day40 代码随想录打卡|二叉树篇---完全二叉树的节点个数

题目&#xff08;leecode T222&#xff09;&#xff1a; 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c…

[Vue]处理一进入页面数据未获取到时的警告

当页面一进入页面就需要展示后台数据时&#xff0c;控制台会类似于报如下的警告 原本的写法如下,我原以为做了 || 0 的处理以后就就可以避免这个问题&#xff0c;但是由于是取的对象里面的属性&#xff0c;所以还是会报错。PS&#xff1a;基本类型的数据可以这样处理。 <top…

SpringCloud-OpenFeign

一 OpenFeign是什么?有什么用? 以往我们是通过 RestTemplate 发起远程调用&#xff0c;如下: 存在问题如下&#xff1a; 代码可读性差&#xff0c;编程体验不统一参数复杂URL难以维护 Feign 是一个声明式的 http 客户端&#xff0c;其作用就是用来把我们解决上述问题的~ 二…

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

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

TCP协议详解及其相关的10个核心机制(面试重点)

TCP协议的报文格式 TCP协议有连接&#xff0c;可靠性传输&#xff0c;面向字节流&#xff0c;全双工。 他的数据格式如图&#xff1a; 根据他的数据格式&#xff0c;在这里我们只知道 16位源端口号&#xff08;表示客户端这里的端口号&#xff09;&#xff0c;16位目的端口号&…

【微服务】docker部署redis,一主二从三哨兵,读写分离

配置redis读写分离 3台虚拟机 创建目录用于挂载 mkdir -p /root/redis/{conf,data,logs} #master配置文件 bind 0.0.0.0 //任何ip都能访问 port 6379 //redis端口号 logfile "/data/redis.log" //日志文件存放位置&#xff0c;启动redis之前设置为空&#xff…

资深开发推荐的IDEA 插件

开发如虎添翼 工欲善其事&#xff0c;必先利其器。想要提升编程开发效率&#xff0c;必须选择一款顺手的开发工具&#xff0c;插件不在多&#xff0c;而在精&#xff0c;作为从业10年的程序员&#xff0c;我目前用到这十几个插件&#xff0c;在平时开发&#xff0c;代码review…

OpenCv之简单的人脸识别项目(登录页面)

人脸识别 一、项目准备二、登录页面1.导入所需的包2.设置窗口2.1定义窗口外观和大小2.2设置窗口背景2.2.1设置背景图片2.2.2创建label控件 3.运行脚本3.1定义识别脚本3.2定义提取脚本3.3定义标注脚本3.4定义人脸比对脚本3.5定义动态处理脚本3.6定义属性判断脚本 4.创建一个退出…