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  # 起始顶点到自身的距离为0
    pq = [(0, start)]  # 使用优先队列存储待访问的顶点
    
    while pq:  # 开始遍历直到优先队列为空
        current_distance, current_vertex = heapq.heappop(pq)  # 从优先队列中弹出当前距离最短的顶点
        
        if current_distance > distances[current_vertex]:  # 如果当前顶点的距离已经被更新过,跳过
            continue
        
        for neighbor, weight in graph[current_vertex].items():  # 遍历当前顶点的相邻顶点
            distance = current_distance + weight  # 计算通过当前顶点到达相邻顶点的距离
            if distance < distances[neighbor]:  # 如果经过当前顶点到相邻顶点的距离更短,则更新相邻顶点的距离并将其加入优先队列
                distances[neighbor] = distance
                heapq.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 defaultdict

class 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+1
        num = [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

                # 新的到达该邻居的次数是当前次数加1
                newnum = current_num + 1

                # 将新的距离、邻居顶点、到达次数加入优先队列
                heapq.heappush(pq, (distance, neighbor, newnum))

        # 如果最终没有找到目标终点,则返回-1
        return -1



  • 分析
  • 与Dijkstra 算法的模板类似但是又有不同地方:
    相同:利用优先队列进行相对应的信息的存储,其实就是实现遍历的一个过程
    不同之处:关注于以出发点为中心的类似一个圆的一个不超过k 步的一个范围

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

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

相关文章

Linux_进程概念

硬件系统 软件系统 进程概念 进程状态 孤儿进程 进程优先级 一.硬件系统 1.1 冯诺依曼体系结构 数学家冯诺依曼提出了计算机制造的三个基本原则&#xff0c;即采用二进制逻辑、程序存储执行以及计算机由五个部分组成&#xff08;运算器、控制器、存储器、输入设备、输出设备&a…

例39:使用List控件

建立一个EXE工程&#xff0c;在窗体上放一个文本框&#xff0c;一个列表框和三个按钮输入如下的代码&#xff1a; Sub Form1_Command1_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd)List1.AddItem(Text1.Text)End SubSub Form1_Command2_BN_Clicked(hWndForm As hWnd, h…

【教程】C++语言基础学习笔记(七)——Array数组

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【C语言基础学习】系列文章 第一章 《项目与程序结构》 第二章 《数据类型》 第三章 《运算符》 第四章 《流程控制》 第五章…

服务流控(Sentinel)

引入依赖 <!-- 必须的 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><!-- sentinel 核心库 --> <dependency><groupId>com.ali…

Rust入门:如何在windows + vscode中关闭程序codelldb.exe

在windows中用vscode单步调试rust程序的时候&#xff0c;发现无论是按下stop键&#xff0c;还是运行完程序&#xff0c;调试器codelldb.exe一直霸占着主程序不退出&#xff0c;如果此时对代码进行修改&#xff0c;后续就没法再编译调试了。 目前我也不知道要怎么处理这个事&am…

npm报错之package-lock.json found. 问题和淘宝镜像源过期问题

1、package-lock.json found. 问题的解决 在执行yarn add react-transition-group -S 安装react-transition-group时出现package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in orde…

Gitee的使用教程(简单详细)

1.安装git&#xff08;我的电脑自带git&#xff0c;我没弄这步QAQ&#xff09; Git (git-scm.com)https://git-scm.com/ 安装好后在桌面点击鼠标右键会出现git GUI 和 git Bash&#xff08;没有的话点击显示更多选项&#xff09; 2.去gitee上注册一个账号 工作台 - Gitee.co…

Hive的Join连接

前言 Hive-3.1.2版本支持6种join语法。分别是&#xff1a;inner join&#xff08;内连接&#xff09;、left join&#xff08;左连接&#xff09;、right join&#xff08;右连接&#xff09;、full outer join&#xff08;全外连接&#xff09;、left semi join&#xff08;左…

耳机壳UV树脂制作私模定制耳塞适合什么样的人使用呢?

耳机壳UV树脂制作私模定制耳塞适合以下人群使用&#xff1a; 对音质要求高的人&#xff1a;私模定制耳塞能够完美契合用户的耳朵形状&#xff0c;减少漏音和外部噪音的干扰&#xff0c;提供更好的音质体验。需要长时间佩戴耳机的人&#xff1a;私模定制耳塞能够提高佩戴舒适度…

【Django】Django内建用户系统

Django内建用户系统 14.1 Django中的用户认证 Django带有一个用户认证系统系统&#xff0c;它处理用户用户账号、组、权限以及基于cookie的用户会话。 用户可以直接使用Django自带的用户表。 官方文档&#xff1a;https://docs.djangoproject.com/zh-hans/2.2/topics/auth/ …

C语言—基础数据类型(含进制转换)

进制转换不多&#xff0c;但我觉得适合小白(我爱夸自己嘿嘿) 练习 1. 确认基础类型所占用的内存空间(提示&#xff1a;使用sizeof 运算符)&#xff1a; 在这里我说一下&#xff0c;long 类型通常占用 4 字节。在 64 位系统上&#xff0c;long 类型通常也可为 8 字节。 格式…

部署JForum2过程。

居然用了两天时间&#xff0c;才把JForum2部署成功。走了一些弯路&#xff0c;主要原因是想当然&#xff0c;以为jdk和tomcat&#xff0c;应该向下兼容&#xff0c;所以就随便选的版本。 一、jdk-17、apache-tomcat-10.1.18-windows-x64&#xff0c;部署完jforum-2.8.2.war,改…

海量数据处理商用短链接生成器平台 - 4

第六章 架构核心技术-池化思想-异步结合 性能优化最佳实践 第1集 RestTemplate里面的存在的问题你知道多少- Broken pipe错误 项目就更新到第六章了&#xff0c;剩下的内容 放百度网盘里面了&#xff0c;需要的来取。 链接&#xff1a;https://pan.baidu.com/s/19LHPw36dsxPB7…

LeetCode、901. 股票价格跨度【中等,单调栈】

文章目录 前言LeetCode、901. 股票价格跨度【中等&#xff0c;单调栈】题目链接及分类思路思路1&#xff1a;暴力思路2&#xff1a;单调栈写法优化&#xff1a;单调栈简化写法(数组替代栈集合) 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、…

LeetCode、1143. 最长公共子序列【中等,二维DP】

文章目录 前言LeetCode、1143. 最长公共子序列【中等&#xff0c;二维DP】题目链接与分类思路2022年暑假学习思路及题解二维DP解决 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者…

如何才能学好JVM?——零基础入门篇

1. JVM是什么&#xff1f; JVM是Java Virtual Machine的简称&#xff0c;它是一个虚拟的计算机&#xff0c;专门为执行Java程序而设计。 你可以想象它是一个能够运行Java字节码的平台&#xff0c;无论你的程序在Windows、Mac还是Linux上&#xff0c;它们都能通过JVM在这些系统…

P1928 外星密码

网址如下&#xff1a; P1928 外星密码 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) C的string真的是太好用辣&#xff01; 思路就是用一个函数来递归翻译 代码如下&#xff1a; #include<iostream> #include<string> #include<cctype> using namespace…

springboot183基于java的公寓报修管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

Microsoft OneNote 图片文字提取

Microsoft OneNote 图片文字提取 1. 文件 -> 新建 -> 我的电脑 -> 名称 -> 位置 -> 创建笔记本2. 插入图片​​​3. 复制图片中的文本References 1. 文件 -> 新建 -> 我的电脑 -> 名称 -> 位置 -> 创建笔记本 ​ 2. 插入图片 ​​​3. 复制图片…

Linux-进程信号

Linux进程信号 初步认识信号信号的存储结构信号的处理方式信号的产生硬件异常产生的信号核心转储sigset_t信号集信号集的操作函数对block表的操作对pending表的操作对handler表的操作信号的捕捉用户态和内核态 信号的处理过程可重入函数volatile关键字 初步认识信号 生活中有哪…