用最简单的示例去理解:Dijkstra最短路径算法

Dijkstra算法是一种用于解决单源最短路径问题的经典算法,它能够计算出从单个源节点到图中所有其他节点的最短路径。

以下是Dijkstra算法的基本步骤:

  1. 初始化:将起始节点的距离设置为0,将所有其他节点的距离设置为无穷大(或一个较大的值)。将起始节点添加到优先级队列中。

  2. 迭代:重复以下步骤直到优先级队列为空:

    • 从优先级队列中取出当前距离最短的节点。
    • 历该节点的所有邻居节点,并更新它们的距离,如果通过当前节点到达邻居节点的路径比已知的最短路径更短,则更新邻居节点的距离,并将其添加到优先级队列中。
  3. 终止当优先级队列为空时,算法结束,所有节点的最短路径已经计算完成。

Dijkstra算法的核心思想是通过不断地松弛边来逐步确定从起始节点到其他节点的最短路径。它保证了每个节点的距离值在算法执行过程中只会被更新一次,因此在没有负权边的情况下,可以得到正确的最短路径。

需要注意的是,Dijkstra算法仅适用于没有负权边的情况,如果图中存在负权边,需要使用其他算法,比如Bellman-Ford算法。

-----------

# 在这个例子中,如果你从节点 1 出发,想找到到达节点 4 的最短路径,会使用 Dijkstra 算法。这意味着你会计算从一个节点到达另一个节点的最短距离。
# 这里是算法如何运作的简化过程:
# 1. 从节点 1 开始,距离初始值设为0,其他节点的距离设为无穷大。
# 2. 考虑从节点 1 出发,到节点 3 的距离是 5,到节点 2 的距离是 10。更新这两个节点的距离。
# 3. 从剩余节点中选择距离最短的一个。现在,节点 3 的距离最短,是5。所以选择节点 3,查看它的相邻节点。
# 4. 从节点 3 到节点 4 的距离是 1,加上先前的距离 5,等于6。所以更新节点 4 的距离为6。
# 5. 同样从节点 2 到节点 4 的距离是 1,加上节点 1 到节点 2 的距离是 10,总共是 11。
但因为 6 比 11 小,所以不会重新更新节点 4,因为已经有了更短的路径。
# 所以,在这种情况下,程序会忽略从节点 2 经过的路径,因为已经有更短的路径(从节点 1 到 3 到 4)。

import heapq  # 导入用于实现优先级队列的模块# 创建一个示例图
# 图的结构是一个字典,键是节点,值是邻接节点和对应的边权重
graph = {1: {2: 10, 3: 5},  # 节点1连接到节点2,权重是10;连接到节点3,权重是52: {4: 1},         # 节点2连接到节点4,权重是13: {4: 1},         # 节点3连接到节点4,权重是14: {}  # 添加节点4,并将其邻接节点设为空字典,因为节点4没有邻接节点
}#     10# (1)---(2)#    |   |#  5 |   | 1#    |   |# (3)---(4)#     1# Dijkstra算法函数
def dijkstra(graph, start):# 创建一个优先级队列pq = []  # 用来存储需要处理的节点# 初始化距离字典,所有节点的初始距离设为无穷大distances = {node: float('inf') for node in graph}distances[start] = 0  # 源节点的距离为0# 创建一个字典来存储每个节点的前驱节点,方便追踪路径previous = {node: None for node in graph}# 将源节点加入优先级队列heapq.heappush(pq, (0, start))  # (距离, 节点)# 处理优先级队列中的节点while pq:print('前pq-queue:',pq)print('前distances:',distances)print('前previous:',previous)print('-----------')# 从优先级队列中取出距离最短的节点current_distance, current_node = heapq.heappop(pq)# 如果当前距离大于已知的最短距离,则继续# 如果发现从当前节点出发的路径到达的某个节点的距离大于已知的距离,则说明已经找到了一条更短的路径,因此可以跳过该节if current_distance > distances[current_node]:continue  # 这条路径不再有效,跳过# 遍历当前节点的邻接节点for neighbor, weight in graph[current_node].items():# 计算从当前节点到邻接节点的距离distance = current_distance + weight# 如果发现更短的路径,则更新if distance < distances[neighbor]:distances[neighbor] = distance  # 更新距离previous[neighbor] = current_node  # 更新前驱节点# 将邻接节点加入优先级队列heapq.heappush(pq, (distance, neighbor))print('更新pq-queue:',pq)print('更新distances:',distances)print('更新previous:',previous)print('-----------')return distances, previous  # 返回最终的距离和前驱节点信息# 从节点1开始运行Dijkstra算法
distances, previous = dijkstra(graph, 1)print("每个节点最短距离:", distances)  # 打印每个节点的最短距离
print("每个节点的前驱节点:", previous)   # 打印每个节点的前驱节点# 在这个例子中,如果你从节点 1 出发,想找到到达节点 4 的最短路径,你会使用 Dijkstra 算法。这意味着你会计算从一个节点到达另一个节点的最短距离。
# 这里是算法如何运作的简化过程:
# 1. 从节点 1 开始,距离初始值设为0,其他节点的距离设为无穷大。
# 2. 考虑从节点 1 出发,到节点 3 的距离是 5,到节点 2 的距离是 10。更新这两个节点的距离。
# 3. 从剩余节点中选择距离最短的一个。现在,节点 3 的距离最短,是5。所以选择节点 3,查看它的相邻节点。
# 4. 从节点 3 到节点 4 的距离是 1,加上先前的距离 5,等于6。所以更新节点 4 的距离为6。
# 5. 同样从节点 2 到节点 4 的距离是 1,加上节点 1 到节点 2 的距离是 10,总共是 11。但因为 6 比 11 小,所以不会重新更新节点 4,因为已经有了更短的路径。
# 所以,在这种情况下,程序会忽略从节点 2 经过的路径,因为已经有更短的路径(从节点 1 到 3 到 4)。# 在Dijkstra算法中,确保每个节点只被访问一次并且在找到更短路径后不会再次考虑该节点的部分通常通过以下方式实现:
# 1. **优先级队列(Priority Queue)的使用**:Dijkstra算法通常使用优先级队列来管理要探索的节点。
# 在每次迭代中,从优先级队列中选择当前距离最短的节点进行处理。这确保了每个节点只被访问一次。
# 2. **距离字典的更新**:在发现更短路径后,会更新距离字典中该节点的距离值。
# 这意味着即使后续有其他路径经过该节点,由于已经发现了更短的路径,因此不会再考虑该节点。
# 3. **跳过已处理节点**:如果在优先级队列中发现某个节点的当前距离已经大于已知的最短距离,则跳过对该节点的处理。
# 这确保了在找到更短路径后不会重复考虑该节点。
# 这些机制确保了Dijkstra算法在搜索过程中每个节点只被访问一次,并且在找到更短路径后不会再次考虑该节点,从而提高了算法的效率和性能。

----------

# 在Dijkstra算法中,确保每个节点只被访问一次并且在找到更短路径后不会再次考虑该节点的部分通常通过以下方式实现:
# 1. **优先级队列(Priority Queue)的使用**:Dijkstra算法通常使用优先级队列来管理要探索的节点。
# 在每次迭代中,从优先级队列中选择当前距离最短的节点进行处理。这确保了每个节点只被访问一次。
# 2. **距离字典的更新**:在发现更短路径后,会更新距离字典中该节点的距离值。
# 这意味着即使后续有其他路径经过该节点,由于已经发现了更短的路径,因此不会再考虑该节点。
# 3. **跳过已处理节点**:如果在优先级队列中发现某个节点的当前距离已经大于已知的最短距离,则跳过对该节点的处理。
# 这确保了在找到更短路径后不会重复考虑该节点。
# 这些机制确保了Dijkstra算法在搜索过程中每个节点只被访问一次,并且在找到更短路径后不会再次考虑该节点,从而提高了算法的效率和性能。

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

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

相关文章

如何在您的域名中使用 Google Apps 创建 SPF 记录

关于 SPF 记录 SPF 记录是一种域名服务&#xff08;DNS&#xff09;记录&#xff0c;用于标识哪些邮件服务器被允许代表您的域发送电子邮件。它与在您的 DNS 区域中添加 MX 或 A 记录一样简单。 为什么它很重要&#xff1f; 如今&#xff0c;几乎所有滥用电子邮件消息都携带…

OpenSPG docker 安装教程

文章目录 前言自述 一、OpenSPG1.介绍 二、安装步骤1.安装服务端2.客户端部署 前言 自述 我最近是想结合chatglm3-6b和知识图谱做一个垂直领域的技术规范的问答系统&#xff0c;过程中也遇到了很多困难&#xff0c;在模型微调上&#xff0c;在数据集收集整理上&#xff0c;在知…

echarts饼图渲染

在Vue中使用ECharts渲染饼图&#xff0c;你可以遵循以下步骤&#xff1a; 1. **安装ECharts**&#xff1a; 在你的Vue项目中&#xff0c;首先需要通过npm或yarn来安装ECharts。 npm install echarts --save 或者 yarn add echarts 2. **引入ECharts**&#xff1a; 在你的Vue组…

Spring中的FileCopyUtils:文件复制的利器与详解

1. 概述 在Spring框架中&#xff0c;FileCopyUtils是一个用于文件复制操作的实用工具类。它提供了一系列静态方法&#xff0c;简化了文件从输入流到输出流、从文件到文件等的复制过程。这些方法都基于NIO&#xff08;New I/O&#xff09;技术&#xff0c;提供了高效的文件复制…

面向侧扫声纳目标检测的YOLOX-ViT知识精馏

面向侧扫声纳目标检测的YOLOX-ViT知识精馏 摘要IntroductionRelated WorkYOLOv-ViTKnowledge DistillationExperimental Evaluation Knowledge Distillation in YOLOX-ViT for Side-Scan Sonar Object Detection 摘要 在本文中&#xff0c;作者提出了YOLOX-ViT这一新型目标检测…

Sealos急速部署生产用k8s集群

最近一段时间部署k8s全部使用sealos了&#xff0c;整体使用感觉良好&#xff0c;基本没有什么坑。推荐给大家。 使用 Sealos&#xff0c;可以安装一个不包含任何组件的裸 Kubernetes 集群。 最大的好处是提供 99 年证书&#xff0c;用到我跑路是足够了。不用像之前kubeadm安装…

【6D位姿估计】FoundationPose 支持6D位姿估计和跟踪 CVPR 2024

前言 本文介绍6D位姿估计的方法FoundationPose&#xff0c;是CVPR 2024的满分论文&#xff0c;支持6D位姿估计和跟踪。 通过大规模的合成数据训练&#xff0c;具有强大的泛化能力&#xff0c;在测试新物体时&#xff0c;无需进行微调。 论文地址&#xff1a;FoundationPose:…

1688数据分析实操技巧||1688商品数据采集接口 数据分析

今天&#xff0c;聊一聊B2B平台的数据分析&#xff0c;以1688国内站为例。 1688平台数据接口 1688也属于阿里巴巴的体系&#xff0c;跟淘宝天猫运营很像&#xff0c;因此很多淘宝天猫的玩法调整后也适用于1688。数据分析也是如此。 在1688搞数据分析&#xff0c;搞数据化运营可…

绘唐3 零基础系列教程

绘唐3 团长董事长,即可下载工具 第一讲:安装注册 日期:2024-04-01 17:50:10 录制文件:查看 第二讲:SD,MJ出图配置演示出图 日期:2024-04-01 18:06:46 录制文件:查看

不使用EF框架实现数据库增删改查

创建一个通用的数据访问层 (DAL) 类&#xff0c;让所有需要操作数据库的 DAL 类都继承这个基类&#xff0c;以实现通用的增删改查方法。下面是一个简单的示例展示如何实现这样的通用基类&#xff1a; public class BaseDal<T> where T : class {protected string connec…

【算法训练 day22 最大二叉树、合并二叉树、二叉搜索树的搜索、验证二叉搜索树】

目录 一、最大二叉树-LeetCode 654思路 二、合并二叉树-LeetCode 617思路 三.二叉搜索树的搜索-LeeCode 700思路 四.验证二叉搜索树-LeeCode 98思路 一、最大二叉树-LeetCode 654 思路 本题还是对数组进行切割&#xff0c;然后建立二叉树&#xff0c;递归方式自然是先序遍历。…

代码随想录leetcode200题之二叉树

目录 1 介绍2 训练3 参考 1 介绍 本博客用来记录代码随想录leetcode200题中二叉树部分的题目。 2 训练 题目1&#xff1a;递归遍历&#xff1a;中序、前序、后序 C模板如下&#xff0c; //中序 void traversal(TreeNode* cur, vector<int>& vec) {if (cur NULL…

【笔试训练】day22

1.添加字符 求最少不相等的位数&#xff0c;可以先求最多相等的位数。 在添加字符之前&#xff0c;A和B最多相等的位数是多少&#xff1f;由于A后面可以添加字符&#xff0c;也就使得A字符可以在B的任意一个位置开始比较。遍历一遍这个比较的起点&#xff0c;从这个起点开始跟…

统计二进制中1的个数

编程题&#xff1a; 求一个整数&#xff0c;在内存当中存储时&#xff0c;二进制1的个数。 目录 1.第一种解法2.第二种解法3.第三种解法 1.第一种解法 一个整型的数字共32个比特位&#xff0c;每个比特位如何判断是否为1&#xff1f;只需让这一位和1进行按位与即可 public s…

Linux中的简单操作 ls/tar/pwd/cd/mkdir/touch 等

目录 前言 安装和卸载软件包 ls 查看指定路径下的文件和文件夹 tar 解压缩/压缩命令 pwd 查看当前路径 cd 改变目录 mkdir 创建目录 递归创建 rm rmdir 删除文件或目录 touch 创建文件 ll、echo、重定向符&#xff08;>,>>&#xff09; ll echo 重定向符…

Vue Router 路由hash和history模式

文章目录 hash和history模式区别Hash 模式History 模式 在 Vue 中&#xff0c;路由的两种主要模式是 hash 和 history&#xff0c;默认的路由模式是hash模式。。这两种模式决定了 URL 的外观以及浏览器如何处理 URL 的变化。 hash和history模式区别 特性Hash 模式History 模…

简单负载均衡

题目描述 某工程师为了解决服务器负载过高的问题&#xff0c;决定使用多个服务器来分担请求消息。 现给定 k 台服务器&#xff08;编号从 1 到 k&#xff09;&#xff0c;以及一批请求消息的信息&#xff0c;格式为到达时刻 负载大小&#xff0c;消息说明&#xff1a; 每个时刻…

SQL查询语句(四)模糊查询

前文介绍的查询语句&#xff0c;无论是利用常规的数学运算符&#xff0c;还是IN&#xff0c;BETWEEN和EXISTS等范围查询关键字&#xff0c;本质上都属于精确查询的范围&#xff0c;也就是说&#xff0c;我们在条件中写明了完全限定死的条件。而有些场景&#xff0c;我们的条件并…

2024OD机试卷-堆内存申请 (java\python\c++)

题目:堆内存申请 题目描述 有一个总空间为100字节的堆,现要从中新申请一块内存, 内存分配 原则为:优先紧接着前一块已使用内存,分配空间足够且最接近申请大小的空闲内存。 输入描述 第1行是1个整数,表示期望申请的内存字节数 第2到第N行是用空格分割的两个整数,表示…

安全继电器的使用和作用

目录 一、什么是安全继电器 二、安全继电器的接线方式 三、注意事项 四、总结 一、什么是安全继电器 安全继电器是由多个继电器与硬件电路组合而成的一种模块&#xff0c;是一种电路组成单元&#xff0c;其目的是要提高安全因素。完整点说&#xff0c;应该叫成安全继电器模…