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,一经查实,立即删除!

相关文章

Linux命令速查表:简洁高效,一表掌握

Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想&#xff0c;是一个性能稳…

四、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;泛…

leetcode算法-位运算

位运算&#xff0c;直接在二进制上进行的按位操作&#xff0c;位运算的种类如下&#xff1a; 1.按位异或^:异或的含义是操作的两位不同&#xff0c;则结果为1&#xff0c;相同则结果为0&#xff0c;所以两个相同的数异或&#xff0c;结果应该是0&#xff0c;3^3的结果是0,3^4的…

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…

Yann LeCun 小传

以下内容整理自 《科学之路》。 Yann LeCun&#xff0c;中文译名杨立昆&#xff0c;1960年出生于法国巴黎附近。他的父亲是一位航空工程师&#xff0c;业余时间喜欢做一些电子产品。 1968年&#xff0c;8岁的杨立昆看了电影《2001太空漫游》。 1978年&#xff0c;高中毕业&a…

AcWing 122 糖果传递(贪心)

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

2.第一个Electron程序

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

maven仓库的加载步骤

仓库加载步骤 Maven 在判断资源来自哪个仓库时&#xff0c;是根据 Maven 项目的配置以及 Maven 的工作机制来进行判断的。以下是 Maven 判断资源仓库的一般步骤&#xff1a; 从 Maven 项目的 pom.xml 文件中读取配置信息&#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-…

“反内卷”代码书写原则

有人相爱&#xff0c;有人夜里开车看海。有人看着这些代码一句话也说不出来。这是一个你的项目应该遵循的垃圾代码书写准则&#xff0c;只有这样写了才能让人看不懂&#xff0c;这才是真正的反内卷之道&#xff0c;请恪守以下原则&#xff0c;时刻铭记&#xff0c;切勿反向操作…

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下载、安装与无限使用详细教…