python算法之 Dijkstra 算法

文章目录

  • 基本思想:
  • 步骤:
  • 复杂度:
  • 注意事项:
  • 代码实现
  • K 站中转内最便宜的航班

Dijkstra 算法是一种用于解决单源最短路径问题的经典算法。该问题的目标是找到从图中的一个固定顶点(称为源点)到图中所有其他顶点的最短路径。

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

基本思想:

  • Dijkstra 算法通过贪心策略逐步扩展已找到的最短路径集合,直到到达目标顶点或者所有顶点都被访问过。

步骤:

  1. 初始化:初始化距离和父节点信息。

    • 创建一个距离字典 distances,用于存储从源点到每个顶点的当前最短距离估计。
    • 初始化源点到自身的距离为 0,其他顶点到源点的距离为正无穷大。
    • 创建一个父节点字典 parents,用于记录最短路径上每个顶点的前一个顶点。
  2. 构建优先队列:将所有顶点及其距离值放入优先队列中。

    • 使用最小堆作为优先队列,距离作为优先级。
  3. 主循环:重复以下步骤直到优先队列为空:

    • 从优先队列中弹出一个顶点 current_vertex,其到源点的距离 current_distance 是已知的最小值。
    • 对于当前顶点的每个相邻顶点 neighbor
      • 计算从源点经过 current_vertex 到达 neighbor 的距离 new_distance
      • 如果 new_distance 小于 distances[neighbor],更新 distances[neighbor]parents[neighbor]
      • (new_distance, neighbor) 插入优先队列,以便下一次选择。
  4. 最终结果:当优先队列为空时,所有顶点的最短路径都已经计算完成,从源点到每个顶点的最短路径长度保存在 distances 字典中,而最短路径上的父节点关系保存在 parents 字典中。

复杂度:

  • 时间复杂度:O((V+E)logV),其中 V 是顶点数量,E 是边数量。
  • 空间复杂度:O(V),存储距离和父节点的字典。

注意事项:

  • Dijkstra 算法要求图中所有边的权值非负。
  • 对于稀疏图,可以使用优先队列实现,而对于稠密图,则可能需要使用 Fibonacci 堆等更复杂的数据结构以获得更好的性能。

Dijkstra 算法是一种十分重要且常用的算法,在网络路由、图形可视化等领域都有广泛应用。

代码实现


import heapq  # 导入 heapq 模块def dijkstra(graph, start):distances = {vertex: float('infinity') for vertex in graph}  # 初始化距离字典,用于存储从起始顶点到各顶点的当前最短距离distances[start] = 0  # 起始顶点到自身的距离为0pq = [(0, start)]  # 使用优先队列存储待访问的顶点while pq:  # 开始遍历直到优先队列为空current_distance, current_vertex = heapq.heappop(pq)  # 从优先队列中弹出当前距离最短的顶点if current_distance > distances[current_vertex]:  # 如果当前顶点的距离已经被更新过,跳过continuefor neighbor, weight in graph[current_vertex].items():  # 遍历当前顶点的相邻顶点distance = current_distance + weight  # 计算通过当前顶点到达相邻顶点的距离if distance < distances[neighbor]:  # 如果经过当前顶点到相邻顶点的距离更短,则更新相邻顶点的距离并将其加入优先队列distances[neighbor] = distanceheapq.heappush(pq, (distance, neighbor))return distances# 示例图
graph = {  # 定义示例图'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}start_vertex = 'A'  # 定义起始顶点
print("从顶点 {} 到各顶点的最短距离:".format(start_vertex))  # 打印提示信息
print(dijkstra(graph, start_vertex))  # 调用 dijkstra 函数并打印结果

K 站中转内最便宜的航班

在这里插入图片描述

import heapq
from collections import defaultdictclass Solution:def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:# 创建一个空的字典用于存储图的邻接关系graph = defaultdict(dict)# 将航班信息填充到图中for a, b, c in flights:graph[a][b] = c# num列表表示从起点src到每个顶点的最小次数,初始值为n+1num = [n + 1] * n  # 优先队列pq,用于存储当前距离、当前顶点、到达当前顶点的次数pq = [(0, src, 0)] while pq:# 从优先队列中弹出当前距离最小的顶点及其距离和到达该顶点的次数current_distance, current_vertex, current_num = heapq.heappop(pq)# 如果当前顶点就是目标终点,则返回当前距离if current_vertex == dst:return current_distance# 如果当前到达该顶点的次数超过了k,或者当前次数已经大于记录的最小次数,则继续下一次循环if current_num > k or current_num > num[current_vertex]:continue# 更新记录到达当前顶点的次数num[current_vertex] = current_num# 遍历当前顶点的所有邻居for neighbor, weight in graph[current_vertex].items():# 新的距离是到达当前顶点的距离加上当前顶点到邻居的距离distance = current_distance + weight# 新的到达该邻居的次数是当前次数加1newnum = current_num + 1# 将新的距离、邻居顶点、到达次数加入优先队列heapq.heappush(pq, (distance, neighbor, newnum))# 如果最终没有找到目标终点,则返回-1return -1
  • 分析
  • 与Dijkstra 算法的模板类似但是又有不同地方:
    相同:利用优先队列进行相对应的信息的存储,其实就是实现遍历的一个过程
    不同之处:关注于以出发点为中心的类似一个圆的一个不超过k 步的一个范围

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

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

相关文章

“从根到叶:深入理解堆数据结构“

一.堆的概念及实现 1.1堆的概念 在数据结构中&#xff0c;堆是一种特殊的树形数据结构。堆可以分为最大堆和最小堆两种类型。 最大堆&#xff1a;对于堆中的任意节点&#xff0c;其父节点的值都不小于它的值。换句话说&#xff0c;最大堆中的根节点是堆中的最大值。并且&…

坚持刷题|重建二叉树

文章目录 题目考察点代码实现实现总结扩展问题从前序和中序遍历中序列构建二叉树题目代码实现与后序实现的异同点 前序和后序可不可以唯一确定一棵二叉树呢&#xff1f; Hello&#xff0c;大家好&#xff0c;我是阿月。坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;今天刷…

2024年危险化学品生产单位安全生产管理人员证考试题库及危险化学品生产单位安全生产管理人员试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年危险化学品生产单位安全生产管理人员证考试题库及危险化学品生产单位安全生产管理人员试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&a…

Solidworks:剖切模型

剖切模型可以看清模型内部。今天设计了一个模型&#xff0c;试验一下如何剖切。 操作很方便&#xff0c;只需要点击一下零件模型上方的剖切按钮&#xff0c;立即就转入剖切视图。剖切后结果如下。 工程图纸中也可以展示剖面视图&#xff0c;操作方法是点击工程图工具页中的“…

Python教程57:海龟画图turtle画动态的流星雨,快让你女朋友看看

---------------turtle源码集合--------------- Python教程91&#xff1a;关于海龟画图&#xff0c;Turtle模块需要学习的知识点 Python教程51&#xff1a;海龟画图turtle画&#xff08;三角形、正方形、五边形、六边形、圆、同心圆、边切圆&#xff0c;五角星&#xff0c;椭…

论文阅读:GamutMLP A Lightweight MLP for Color Loss Recovery

这篇文章是关于色彩恢复的一项工作&#xff0c;发表在 CVPR2023&#xff0c;其中之一的作者是 Michael S. Brown&#xff0c;这个老师是加拿大 York 大学的&#xff0c;也是 ISP 领域的大牛&#xff0c;现在好像也在三星研究院担任兼职&#xff0c;这个老师做了很多这种类似的工…

【从零到Offer】MySQL最左匹配

前言 ​ 相信大家在日常开发时&#xff0c;也经常能听到“最左匹配”这个词&#xff0c;那么什么是最左匹配呢&#xff1f;本篇文章就带你一起探索“最左匹配”的神奇秘密。 什么是最左匹配 ​ 最左匹配&#xff0c;通常指的是最左前缀匹配原则&#xff0c;即MySQL在检索数据…

C++ 特殊类的实现

一、请设计一个类&#xff0c;不能被拷贝 拷贝只会放生在两个场景中&#xff1a;拷贝构造函数以及赋值运算符重载&#xff0c;因此想要让一个类禁止拷贝&#xff0c;只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 在C98中&#xff1a;将拷贝构造函数与赋值运算符重载…

今天:旧时是这样“破五迎福”

昨&#xff08;正月初四&#xff09;天&#xff0c;笔者——“ 人民体验官 ”&#xff0c; 为了推广人民日报官方微博文化产品所发表在10余个网站自媒体平台上的文章《今天&#xff1a;大年初四迎灶神爷》&#xff0c;不知何故被笔者寄居养老城市的自媒体论坛反复拒之门外&…

Imgui(2) | macOS 绘制 CPU 占用率曲线

Imgui(2) | macOS 绘制 CPU 占用率曲线 文章目录 Imgui(2) | macOS 绘制 CPU 占用率曲线0. 简介1. 绘制曲线 - 以正弦函数为例1.1 基于 sf::RectangleShape 的渲染 - 不好看&#xff0c;效率低1.2 基于 sf::VertexArray 的绘制 2. 获取和绘制所有 CPU 的占用率2.1 测试程序 - 用…

LeetCode、136. 只出现一次的数字【简单,位运算】

文章目录 前言LeetCode、136. 只出现一次的数字【简单&#xff0c;位运算】题目链接与分类思路异或一遍运算 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术…

测试西门子博途S7-PLCSIM Advanced V5.0的使用

原创 honeytree 西门子博途S7-PLCSIM Advanced V5.0能支持S7-1500&#xff0c;S7-1500R/H&#xff0c;ET200SP&#xff0c;ET200pro的仿真&#xff0c;用此仿真器可以模拟实际的PLC&#xff0c;用于其他软件的连接&#xff0c;比如上位机软件、触摸屏软件,自己用高级语音开发…