图搜索算法-最短路径算法-戴克斯特拉算法

相关文章:
数据结构–图的概念
图搜索算法 - 深度优先搜索法(DFS)
图搜索算法 - 广度优先搜索法(BFS)
图搜索算法 - 拓扑排序

最短路径算法

自从有了导航,人们再也不怕去陌生地方,说走就走的旅行一点都不困难。打开导航,它总能告诉你怎样去到想要去的地方,并且往往已经是优化了的路线,路程最短或用时最少。社交应用已经占据手机使用的大部分时间了,在微信,英领,QQ等平台上查看朋友简介,平台也会告诉我们谁是大家共同朋友,或者告诉你,某个人和你有共同朋友,要不你们也认识一下。这些都是应用了最短路径算法,通过算法可以快速给出两点之间的最短距离,可以计算两点间成本最低的路线。解决最短路的问题有好几种算法,戴克斯特拉(Dijkstra)算法,贝尔曼-福特(Bellman-Ford)算法,插点算法(Floyd)等。

戴克斯特拉算法(Dijkstra)

虽然导航好像在最近10几年才普及使用,但早在1960年美国已经开始利用军事卫星来做导航,而戴克斯特拉(Dijkstra)算法早在1956年被荷兰计算机科学家艾兹赫尔·戴克斯特拉提出。它用于求解从单源结点到图中所有其他结点的最短路径,下面来分析这个算法是怎样运行的,首先来构建一个有权无向图,如图所示。
在这里插入图片描述
(1)设定结点【A】为源结点。
(2)创建一个集合【short_path_set】记录已计算的最小距离结点,也称为最短路径树集合。刚开始的时候,集合为空。
(3)创建一个字典【distance】记录源结点与每个结点的最小距离值,初始化为源结点的距离0,其余结点为无穷大(Max),【“A”:0, Max, Max, Max, Max, Max, Max, Max, Max】。现在把源结点放到【short_path_set】集合中,然后它相邻的结点是【D】和【E】,这时候可以更新【distance】为【“A”:0, “D”:4, “E”:6, Max, Max, Max, Max, Max, Max】,如图所示。

在这里插入图片描述

注意:圆圈内的代表是结点值,上面的数值代表结点到源结点的距离,灰色圆圈代表已经在【short_path_set】集合中。

(4)选取【distance】里面最小距离值,并且不在【short_path_set】集合中的结点,因此选择结点【D】,并放进集合中。然后更新结点【D】相邻结点的距离,如图所示。
在这里插入图片描述
(5)按同样的方式寻找下一个结点,此时为结点【E】,然后更新该结点邻近结点的距离,如图所示。
在这里插入图片描述
(6)这时候【distance】的值为【“A”:0, “D”:4, “E”:6, “B”:12, “H”:17, “F”:10, Max, Max, Max】,【short_path_set】的值为(“A”,“D”,“E”),这时候按同样方式挑选结点【F】,然后更新邻接节点,便发现结点【H】的距离发生改变,如图所示。
在这里插入图片描述
(7)然后挑选结点【B】,然后更新邻接节点,这个时候结点【H】的距离又缩小为13,如图所示。
在这里插入图片描述
(8)同理挑选结点【C】,然后更新邻接节点,如图所示。
在这里插入图片描述
(9)后面按同样方式挑选结点【H】,再到结点【M】,最后是结点【J】,直到所有结点都包含到【short_path_set】集合中,最后结果如图所示。
在这里插入图片描述
最终【distance】的值为【“A”:0, “D”:4, “E”:6, “B”:12, “H”:13, “F”:10, “C”:12, “M”:19, “J”:22】。此算法需要遍历所有结点,而且要对每个结点遍历所有邻接结点,因此极端情况下,所有结点都互相邻接,那么它的时间复杂度为O(N^2),N为结点数量。空间上主要用到一个大小为N的【distance】列表来保存每个结点到源结点的最小距离,因此空间复杂度为O(N)。

注意:这个算法和前面最小生成树里面的普里姆算法非常相似,普里姆算法中的结点键值不是累加起来,而是一条边上的权重和相邻结点的键值和。

现在用代码把上面的运算过程表现出来,首先创建【GraphDijkstra】类继承【GraphArray】类带有邻接矩阵录入功能,dijkstra()函数是算法主程序,最后结果通过print_result()函数输出每个结点到源结点的最短距离。

import sys  # 引入系统参数,获取系统支撑的最大值
class GraphDijkstra(GraphArray):
    """这是寻找单源结点到其余结点的最短路径"""
    def print_result(self, dist): 
        print("结点 \t距离源结点的距离")
        for v in range(self.amount): 
            print(self.points[v], "\t", dist[v])
    def min_distance(self, dist, short_path_set):
        # 寻找结点到源结点最短距离
        min_dist = sys.maxsize #初始化最小距离为系统最大值
        for v in range(self.amount):
            # 寻找最小距离的结点,并且不在最短路径树集合中
            if dist[v] <= min_dist and v not in short_path_set: 
                min_dist = dist[v] 
                min_index = v 
        return min_index 
    def dijkstra(self, source):
        # dijkstra算法主程序,遍历所有结点,放进short_path_set集合中,求得所有结点到源结点的最小距离
        distance = [sys.maxsize] * self.amount 
        distance[source] = 0
        short_path_set = set() # 初始化集合为空
        for _ in range(self.amount):
            # 寻找最小距离的结点,并且不包含在最短路径树集合中
            # 而且源结点总是作为第一个结点进入集合
            u = self.min_distance(distance, short_path_set)
            short_path_set.add(u) # 把结点添加到集合中
            # 重新遍历邻接结点,更新结点间最小距离的值
            for v in range(self.amount): 
                if self.graph[u][v] > 0 and v not in short_path_set and distance[v] > distance[u] + self.graph[u][v]: 
                        distance[v] = distance[u] + self.graph[u][v] #符合条件,更新最短路径值
        self.print_result(distance) # 输出结果

根据例子,构建一个邻居矩阵作为输入,来验证程序。

g = GraphDijkstra(['A','B','C','D','E','F','H','M','J']) 
g.graph = [[0, 0, 0, 4, 6, 0, 0, 0, 0], 
        [0, 0, 9, 8, 0, 0, 1, 7, 0], 
        [0, 9, 0, 0, 0, 2, 0, 11, 10], 
        [4, 8, 0, 0, 0, 0, 13, 0, 0],
        [6, 0, 0, 0, 0, 4, 0, 0, 0], 
        [0, 0, 2, 0, 4, 0, 5, 0, 0], 
        [0, 1, 0, 13, 0, 5, 0, 0, 0], 
        [0, 7, 11, 0, 0, 0, 0, 0, 3], 
        [0, 0, 10, 0, 0, 0, 0, 3, 0] 
        ]; 
g.dijkstra(0)  # A作为源结点
# -------------结果-------------------
结点      距离源结点的距离
A        0
B        12
C        12
D        4
E        6
F        10
H        13
M        19
J        22

对照例子最后的结果,两者是一致的。大家可以尝试换一个源结点,如把结点【B】换作为源结点,再重新计算结果,如下所示。

g.dijkstra(1)  # B作为源结点

这样将会得到完全不一样的结果,大家可以多运行几次,以此熟悉算法运算过程。

更多内容

想获取完整代码或更多相关图的算法内容,请查看我的书籍:《数据结构和算法基础Python语言实现》

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

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

相关文章

mysql查询优化索引篇

其实在写这篇文章之前,也对查询优化做过一些设置,但这次则更为具体一点,之前做的无非就是增加查询字段的索引,让select里和where里的内容全部都包含在索引内(覆盖索引不走回表的基本概念),但这次这么做的时候发现了一些问题,这也是我接下来要提到的,而且之前使用的是sqlserver的…

【生信技能树】GEO数据挖掘全流程

R包的安装&#xff0c;每次做分析的时候先运行这段代码把R包都安装好了&#xff0c;这段代码不需要任何改动&#xff0c;每次分析直接运行。 options("repos""https://mirrors.ustc.edu.cn/CRAN/") if(!require("BiocManager")) install.packag…

苹果M4芯片:大模型本地运算的转折点

在人工智能和机器学习领域&#xff0c;大模型的兴起对硬件提出了前所未有的挑战。苹果公司最近推出的M4芯片&#xff0c;被视为其在这场竞赛中的“第一式”。本文将探讨M4芯片的特点&#xff0c;并与其他芯片进行比较。 M4芯片的亮点 Neural Engine算力&#xff1a;M4芯片的…

OpenStack虚拟机管理实例

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、OpenStack计算服务 1、什么是Nova 2、Nova所用的虚拟技术 3、Nova的系统架构 4、虚拟机实例化流程 一、示例 1、验证Nova服务 2、试…

柔性数组+结构体类型转换

柔性数组&#xff1a;在结构体中声明的时候仅作为占位符&#xff0c;好处是地址是连续的 强制类型转换&#xff1a;可用于通信双方进行信息交流 #include <iostream> #include <string.h>struct DataWater {int count;float size;char buf[0]; }; // dbuf相当于是…

传输文件协议FTP与LFTP

目录 一.简介 二. FTP基础 主动模式&#xff08;Active Mode&#xff09;&#xff1a; 被动模式&#xff08;Passive Mode&#xff09;&#xff1a; 三. Vsftp 服务器简介 四. Vsftpd配置 1. 安装vsftpd&#xff08;ftp服务端&#xff09; 2.编辑配置文件 &#xff08;…

视频汇聚管理/安防监控系统EasyCVR如何开启和调用验证码登录接口?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚融合管理平台EasyCVR既具备传统安防视…

【补充】图神经网络前传——Node2vec

Node2Vec【图神经网络论文精读】_哔哩哔哩_bilibili 解决的问题&#xff1a;图嵌入 把每一个节点编码成一个d维的低维、稠密&#xff08;不是one-hot&#xff09;、连续&#xff08;不是离散的&#xff0c;是实数->有助于保存更多的信息&#xff09;向量&#xff0c;并且&a…

安装Tomcat

下载 Tomcat 软件包 前往 Apache Tomcat 官网:Apache Tomcat - Apache Tomcat 10 Software Downloads在网站上找到最新版本的 Tomcat&#xff0c;选择下载对应的压缩包&#xff08;通常是 .zip 或 .tar.gz 格式&#xff09;。下载完成后&#xff0c;解压缩到您选择的目录。 配…

【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手

文章目录 一、前言二、绘制效果三、ConstraintLayout 使用方法3.1 创建布局文件3.2 替换配置3.3 设置约束&#xff0c;步骤13.4 设置约束&#xff0c;步骤23.5 其他设置 四、结束 一、前言 在进行Android APP开发过程中&#xff0c;减少layout嵌套即可改善UI的绘制性能&#x…

考研数学|强化《660》+《880》这样刷,太丝滑了❗️

660题880题需要大概两个月才能做完 660题和880题都是很高质量的题集&#xff0c;所以做起来一点也不轻松。 每年都会有学生暑假两个月只做了一本660题的情况&#xff0c;因为题目实在是太难&#xff0c;有点做不下去的感觉。 不过不要担心&#xff0c;暑假就是刷题发现问题的…

一个小调整,竟然让交换机、路由器的CPU占用率降低了50%

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 下午好&#xff0c;我的网工朋友。 在信息时代下&#xff0c;不仅仅在网络工程领域&#xff0c;高CPU占用率都是一个非常常见的问题&#xff0c;…

ESP32-S3+86盒线控器方案,含开发时问题技术解答

随着智能家居产品越来越多&#xff0c;线控器应用也加大&#xff0c;86盒线控器跟智能吹风机联动&#xff0c;跟中央空调联动&#xff0c;下面讲下ESP32-S386盒线控器方案在开发中遇到的问题。 一、ESP32-S386盒线控器方案&#xff1a; 1、无需网关&#xff0c;可以直接连家里…

Flutter 玩转动画 + 自定义View 实现积分或金币领取流程动画

一、效果图 二、主要涉及的知识点 AnimationController、Animation、FractionalTranslation 动画Api的运用CustomPainter 自定义View以及每个时机的把握 主要是写篇博客来记录一下这个功能的实现&#xff0c;具体代码就看源代码了&#xff0c;有疑问可以私信沟通 源代码下载…

【高阶数据结构】并查集 {并查集原理;并查集优化;并查集实现;并查集应用}

一、并查集原理 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类…

Java的类和对象(一)—— 初始类和对象,this关键字,构造方法

前言 从这篇文章开始&#xff0c;我们就进入到了JavaSE的核心部分。这篇文章是Java类和对象的第一篇&#xff0c;主要介绍类和对象的概念&#xff0c;this关键字以及构造方法~~ 什么是类&#xff1f;什么是对象&#xff1f; 学过C语言的老铁们&#xff0c;可以类比struct自定义…

弹幕游戏-压力测试 Python-Locust模拟送礼物

Hey&#xff0c;读者们&#xff01;今天给大家带来一个Python性能测试的新玩法——使用Locust模拟发送礼物。是不是听起来就很酷&#xff1f;&#x1f60e; &#x1f3af;目标 想象一下&#xff0c;在直播平台上&#xff0c;你希望测试某个直播间的礼物发送功能。那么&#x…

通义千问 1.5 -7B fine-tune验证

尝试对对中文数据进行finetune验证&#xff0c;测试模型的可优化方向。下面是代码的详细情况 代码实现 from datasets import load_dataset from transformers import (AutoModelForCausalLM,AutoTokenizer,BitsAndBytesConfig,HfArgumentParser,AutoTokenizer,TrainingArgum…

Spring学习①__Spring初识

Spring Spring初识一、框架二、Spring&#xff08;春天&#xff09;简介Spring官网Spring是什么?Spring介绍拓展 Spring初识 一、框架 ​框架就是一些类和接口的集合&#xff0c;通过这些类和接口协调来完成一系列的程序实现。 JAVA框架可以分为三层&#xff1a; 表示层业务…

视频号小店,一个不用直播就可以变现的项目!创业首选!

大家好&#xff0c;我是电商小V 想要创业或者是想要利用视频号变现的小伙伴可以说是很多的&#xff0c;因为视频号这两年的流量是非常大的&#xff0c;甚至即将超越抖音的流量&#xff0c;因为视频号背靠腾讯平台&#xff0c;也是不缺少流量的&#xff0c;并且视频号的流量是可…