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.mzph.cn/news/682498.shtml

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

相关文章

四、OpenAI之文本生成模型(Text Generation)

文本生成模型 OpenAI的文本生成模型(也叫做生成预训练的转换器(Generative pre-trained transformers)或大语言模型)已经被训练成可以理解自然语言、代码和图片的模型。模型提供文本的输出作为输入的响应。对这些模型的输入内容也被称作“提示词”。设计提示词的本质是你如何对…

ELAdmin 配置定时任务

定义方法 在自己的 Module 中写个要执行的方法。 比如获取微信公众号的 accessToken&#xff0c;每两个小时更新一次。这种的其实使用 Spring 的 Scheduled 更方便些&#xff0c;此处仅为演示。 package me.zhengjie.mp.task;import com.alibaba.fastjson.JSON; import lombo…

java的面向对象编程(oop)——认识泛型

前言&#xff1a; 打好基础&#xff0c;daydayup! 泛型 1&#xff0c;认识泛型&#xff1a; 定义类&#xff0c;接口&#xff0c;方法时&#xff0c;同时声明了一个或多个类型变量&#xff08;例&#xff1a;<E>&#xff09;,称为泛型&#xff0c;泛型接口&#xff0c;泛…

springboot743二手交易平台

springboot743二手交易平台 获取源码——》公主号&#xff1a;计算机专业毕设大全

电子元器件基础2---电容

两个相互靠近的导体&#xff0c;中间夹一层不导电的绝缘介质&#xff0c;这就构成了电容器。当电容器的两个极板之间加上电压时&#xff0c;电容器就会储存电荷。电容器的电容量在数值上等于一个导电极板上的电荷量与两个极板之间的电压之比。电容器的电容量的基本单位是法拉(F…

C语言学习day12:for循环

前面学了dowhile循环&#xff0c;今天我们来学习经常用到的for循环&#xff1a; for循环&#xff1a; 例子&#xff1a; int main() {//int i;for (int i 0; i < 10;i) {printf("%d\n",i);};system("pause");return EXIT_SUCCESS; } 解释&#xff…

SNMP 简单网络管理协议、网络管理

目录 1 网络管理 1.1 网络管理的五大功能 1.2 网络管理的一般模型 1.3 网络管理模型中的主要构件 1.4 被管对象 (Managed Object) 1.5 代理 (agent) 1.6 网络管理协议 1.6.1 简单网络管理协议 SNMP 1.6.2 SNMP 的指导思想 1.6.3 SNMP 的管理站和委托代理 1.6.4 SNMP…

AcWing 122 糖果传递(贪心)

[题目概述] 有 n 个小朋友坐成一圈&#xff0c;每人有 a[i] 个糖果。 每人只能给左右两人传递糖果。 每人每次传递一个糖果代价为 1。 求使所有人获得均等糖果的最小代价。 输入格式 第一行输入一个正整数 n&#xff0c;表示小朋友的个数。 接下来 n 行&#xff0c;每行一个…

2.第一个Electron程序

目录 一、前言二、基本运行结构三、代码详解四、打包 一、前言 原文以及系列文章后续请参考&#xff1a;第一个Electron程序 上一章我们完成了Electron的环境搭建&#xff0c;本章就开始详解如何使用Electron开发一个完整的Electron桌面端程序。 注意开发环境&#xff0c;个…

【王道数据结构】【chapter5树与二叉树】【P158t6】

二叉树按二叉链表形式存储&#xff0c;试编写一个判别二叉树是否是完全二叉树的算法 #include <iostream> #include <queue> typedef struct treenode{char data;struct treenode *left;struct treenode *right; }treenode,*ptreenode;ptreenode buytreenode(char …

2024.2.14

二维数组实现杨辉三角形 #include<stdio.h> #include<string.h> int main(int argc, const char *argv[]) {int n;scanf("%d",&n);int a[n][n];for(int i0;i<n;i){for(int j0;j<i;j){if(j0||ij){ a[i][j]1;}else{a[i][j]a[i-1][j]a[i-1][j-…

docker 2:安装

docker 2&#xff1a;安装 ‍ ubuntu 安装 docker sudo apt install docker.io‍ 把当前用户放进 docker 用户组&#xff0c;避免每次运行 docker 命都要使用 sudo​ 或者 root​ 权限。 sudo usermod -aG docker $USER​id $USER ​看到用户已加入 docker 组 ​​ ‍ …

CSS介绍

本章目标&#xff1a; CSS概述 三种样式表 简单选择器 复合选择器 盒子模型 常用背景样式 浮动 常用文本样式 伪类样式 列表样式 表格样式 定位 一、CSS概述: CSS&#xff1a;cascading style sheets-层叠样式表 专门负责对网页的美化 二、有三种使用方式&…

SpringBoot与虚拟线程,接口吞吐量成倍增加,太爽了!

我们看一下如何在spring-boot中利用loom虚拟线程。 我们将做一些负载测试&#xff0c;看看虚拟线程和普通线程的响应时间如何。 让我们快速设置我们的 Spring Boot 项目。 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http:/…

【开源图床】使用Typora+PicGo+Gitee搭建个人博客图床

准备工作&#xff1a; 首先电脑得提前完成安装如下&#xff1a; 1. nodejs环境(node ,npm):【安装指南】nodejs下载、安装与配置详细教程 2. Picgo:【安装指南】图床神器之Picgo下载、安装与配置详细教程 3. Typora:【安装指南】markdown神器之Typora下载、安装与无限使用详细教…

JavaScript中如何判断数据类型

在JavaScript中&#xff0c;判断数据类型是我们在日常开发中经常会遇到的问题。正确地判断数据类型不仅有助于我们编写出更加健壮的代码&#xff0c;还可以提高程序的可读性和可维护性。本文将为大家介绍几种判断数据类型的方法 使用typeof运算符&#xff1a; typeof运算符可以…

[NSSRound#17 Basic]WEB

1.真签到 看robots.txt 密码先base32再base64得到md5加密的密文&#xff0c;在线解得到密码为Nss hint用16进制转字符串&#xff0c;提示新生赛遇到过 是一个敲击码加密 账号是ctfer,登录之后源码提示在F111n4l.php 要求nss参数若比较等于732339662&#xff0c;但是不能是数…

关于idea无法检测出lombok,导致代码爆红的处理

为啥需要本地安装lombok插件&#xff1f; 编译错误提示&#xff1a;Lombok 使用注解来自动生成代码&#xff0c;这些代码在编译时会由 Lombok 插件进行处理。如果没有安装 Lombok 插件&#xff0c;IDEA 在编译过程中可能会报告错误&#xff0c;因为它无法识别并处理 Lombok 注解…

【RL】Bellman Optimality Equation(贝尔曼最优等式)

Lecture3: Optimal Policy and Bellman Optimality Equation Definition of optimal policy state value可以被用来去评估policy的好坏&#xff0c;如果&#xff1a; v π 1 ( s ) ≥ v π 2 ( s ) for all s ∈ S v_{\pi_1}(s) \ge v_{\pi_2}(s) \;\;\;\;\; \text{for all…

Python数据科学:Scikit-Learn机器学习

4.1Scikit-Learn机器学习 Scikit-Learn使用的数据表示&#xff1a;二维网格数据表 实例1&#xff1a;通过Seaborn导入数据 def skLearn():scikit Learn基本介绍:return:import seaborn as sns#导入Iris数据集#注&#xff1a;一般网络访问不了iris sns.load_dataset(iris)ir…