【最短路径算法】一文掌握Dijkstra算法,详解与应用示例+代码

news2024/12/23 9:40:49

目录

1 Dijkstra算法

2 Dijkstra算法的步骤

3 Dijkstra算法python实现

4 Dijkstra算法应用示例详解


1 Dijkstra算法

        Dijkstra算法(迪杰斯特拉算法)是一种用于在加权图中查找从一个起始节点到所有其他节点的最短路径的算法。该算法最初由荷兰计算机科学家Edsger W. Dijkstra于1956年提出。Dijkstra算法适用于带有非负权重的有向图或无向图。

特点和限制:

  • Dijkstra算法仅适用于非负权重的图,因为它依赖于贪婪策略来选择当前最短路径。
  • 它可以找到从起始节点到所有其他节点的最短路径,因此适用于单源最短路径问题。
  • Dijkstra算法不会处理负权边,如果图中存在负权边,应该使用其他算法,如Bellman-Ford算法。
  • 算法的时间复杂度取决于数据结构的选择,一般情况下是O(V^2)或O(Vlog(V)),其中V是节点数。如果使用优先队列来优化,时间复杂度可以减小到O(Elog(V)),其中E是边数。

        Dijkstra算法在许多领域广泛应用,包括路线规划、网络路由、资源分配和许多其他需要找到最短路径的应用。

2 Dijkstra算法的步骤

  1. 创建一个空的最短路径字典,其中每个节点的距离设置为无穷大,起始节点的距离设置为0。

  2. 创建一个空的已访问节点集合。

  3. 从未访问的节点中选择距离起始节点最近的节点,标记为已访问。

  4. 对于已访问节点的所有邻居,计算通过已访问节点到达它们的距离,并更新最短路径字典。

  5. 重复步骤3和4,直到所有节点都被访问。

3 Dijkstra算法python实现

以下是Python中使用Dijkstra算法实现的示例代码,用于查找从起始节点到其他节点的最短路径:

import heapq

def dijkstra(graph, start):
    # 创建一个距离字典,用于存储每个节点到起始节点的距离
    distances = {node: float('inf') for node in graph}
    distances[start] = 0
    
    # 创建一个优先队列,以便选择下一个节点
    priority_queue = [(0, start)]

    while priority_queue:
        current_distance, current_node = heapq.heappop(priority_queue)

        # 如果当前距离大于已知距离,跳过
        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
                heapq.heappush(priority_queue, (distance, neighbor))

    return distances

# 创建一个示例图
graph = {
    'A': {'B': 2, 'D': 1},
    'B': {'A': 2, 'C': 3, 'E': 2},
    'C': {},
    'D': {'E': 1},
    'E': {}
}

# 起始节点
start_node = 'A'

# 调用Dijkstra算法函数
shortest_distances = dijkstra(graph, start_node)

# 打印最短路径和距离
for node, distance in shortest_distances.items():
    print(f'Shortest distance from {start_node} to {node} is {distance}')

运行: 

        这段代码定义了一个 dijkstra 函数,用于执行Dijkstra算法。它接受一个图的表示和起始节点作为参数,并返回一个包含从起始节点到其他节点的最短路径的字典。然后,我们创建一个示例图,并使用Dijkstra算法找到从节点 A 到其他节点的最短路径。

        请注意,你可以根据你的需求更改示例图和起始节点,以便应用Dijkstra算法到你的具体问题中。

4 Dijkstra算法应用示例详解

假设我们有以下有向图:

在这个示意图中,有向图包括节点 A、B、C、D 和 E,以及它们之间的带权重的边。边的数字表示权重或距离。我们的目标是找到从节点 A 到其他节点的最短路径。

Dijkstra算法的执行步骤:

  1. 初始化:开始时,我们选择节点 A 作为起始节点,并将其距离设置为 0。同时,将其他节点的距离初始化为无穷大,表示尚未知道到达它们的最短路径。

  2. 选择下一个节点:首先,我们选择节点 A 作为当前节点。它是起始节点,距离已知。

  3. 更新距离:我们计算从节点 A 到其邻居节点 B 和 C 的距离,并将这些距离记录下来。当前已知的最短距离是从 A 到 B 的距离为 4,从 A 到 C 的距离为 2。

  4. 选择下一个节点:现在,我们选择距离最短的节点 C 作为当前节点。

  5. 更新距离:我们计算从 A 经过 C 到达其邻居节点 B 和 D 的距离,并将这些距离记录下来。距离从 A 经过 C 到 B 的距离变为 4 + 5 = 9,从 A 经过 C 到 D 的距离变为 2 + 5 = 7。

  6. 选择下一个节点:然后,我们选择距离最短的节点 B 作为当前节点。

  7. 更新距离:我们计算从 A 经过 B 到达其邻居节点 D 的距离,并将这个距离记录下来。距离从 A 经过 B 到 D 的距离变为 4 + 5 + 3 = 12。

  8. 选择下一个节点:最后,我们选择距离最短的节点 D 作为当前节点。

  9. 更新距离:我们计算从 A 经过 D 到达其邻居节点 E 的距离,并将这个距离记录下来。距离从 A 经过 D 到 E 的距离变为 4 + 5 + 3 + 7 = 19。

  10. 完成:所有节点都已被访问,算法结束。

以上最短路径从节点 A 到其他节点的距离如下: 

  • A到A是 0
  • A到B是 9
  • A到C是 2
  • A到D是 12
  • A到E是 19

        这个示意图展示了Dijkstra算法是如何逐步找到最短路径,并在每一步中选择距离最短的节点。算法的关键思想是贪婪地选择当前最短路径,以逐步构建最短路径树。


以下是Python代码示例,演示如何使用Dijkstra算法找到从节点 A 到其他节点的最短路径:

import networkx as nx
import matplotlib.pyplot as plt

# 创建一个有向图
G = nx.DiGraph()

# 添加节点
nodes = ['A', 'B', 'C', 'D', 'E']
G.add_nodes_from(nodes)

# 添加边和权重
edges = [('A', 'B', 4), ('A', 'C', 2), ('B', 'C', 5), ('B', 'D', 10), ('C', 'D', 3), ('D', 'E', 7), ('E', 'B', 8)]
G.add_weighted_edges_from(edges)

# 定义起点
start_node = 'A'

# 运行Dijkstra算法
shortest_paths = nx.single_source_dijkstra(G, source=start_node)

# 提取最短路径信息
shortest_distances, shortest_path_predecessors = shortest_paths

# 修正labels的格式
labels = {(edge[0], edge[1]): edge[2] for edge in G.edges(data='weight')}

# 可视化图
pos = nx.spring_layout(G, seed=42)  # 布局算法,使图看起来更美观

plt.figure(figsize=(10, 6))
nx.draw(G, pos, with_labels=True, node_size=800, node_color='lightblue', font_size=12, font_weight='bold')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels, font_size=10)

# 绘制最短路径
for node in nodes:
    if node != start_node:
        path = nx.shortest_path(G, source=start_node, target=node)
        path_edges = [(path[i], path[i + 1]) for i in range(len(path) - 1)]
        nx.draw_networkx_edges(G, pos, edgelist=path_edges, edge_color='red', width=2)

plt.title("Dijkstra Algorithm - Shortest Paths")
plt.show()

# 打印最短路径和距离
for node, distance in shortest_distances.items():
    if node != start_node:
        path = nx.shortest_path(G, source=start_node, target=node)
        print(f"Shortest path from {start_node} to {node}: {path}, Distance: {distance}")

 

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

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

相关文章

JVM 基础篇:类加载器

一.了解JVM 1.1什么是JVM JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟计算机功能来实现的&#xff0c;JVM屏蔽了与具体操作系统平台相关的信息&#xff0c;Java程序只需…

通讯录和内存动态管理

目录 (通讯录)动态增长版 实现效果 找单身狗 题目 源码 思路 三个内存函数的模拟实现 模拟实现strncpy 模拟实现strncat 模拟实现atoi (通讯录)动态增长版 该版本通讯录在原版的基础上增加了检查容量函数&#xff0c;实现了通讯录的动态…

在PS中轻松实现肖像磨皮,感受Imagenomic Portraiture 4的强大

每个人都希望自己的肖像照片看起来漂亮、清晰并且光滑。然而&#xff0c;在处理肖像照片时&#xff0c;要达到这些效果通常需要花费大量时间和精力。如果您正在寻找一种简单快捷的方法来优化您的肖像照片&#xff0c;那么Imagenomic Portraiture 4插件将是您的理想选择。 Imag…

单接口的批量测试如何实现

一、痛点&#xff1a;一条测试数据对应一个测试方法 前面的章节中我们已经写代码实现了登录接口的处理调用&#xff0c;但是一个接口往往是需要多条测试用例才能完整的覆盖到每一种情况&#xff0c;针对于单接口多条测试用例需要执行的情况&#xff0c;该如何处理呢&#xff0…

uboot移植之mx6ull_alientek_nand.h文件详解一

一. 简介 mx6ull_alientek_nand.h文件是 开发板的 uboot的一个配置文件。每个开发板都有一个 .h的配置文件。 mx6ull_alientek_nand.h文件其实是 之前针对正点原子ALPHA开发板移植的 Uboot配置文件。 本文简单分析一下 针对正点原子ALPHA开发板的 配置文件&#xff1a; mx6u…

STL模拟实现—vector

引言&#xff1a;本篇文章主要是模拟实现vector&#xff0c;但不同于stl中vector的成员变量都是迭代器&#xff0c;这个自定义的vector是一个T* 的数据变量和一个int类型的size和int类型的capacity。&#xff08;有时间再写三个迭代器的版本吧&#xff01;&#xff09; 首先来看…

Redis学习(第八章缓存策略)

目录 RdisExample 课程介绍 1.Redis介绍 2.Redis 安装 3. Redis的数据结构 4. Redis缓存特性 5. Redis使用场景 6. Redis客户端-Jedis 7. Jedis Pipeline 8. Redis缓存策略 学习资料 QA 相关问题 http, socket ,tcp的区别 RdisExample 项目代码地址&#xff1a;htt…

Leetcode—104.二叉树的最大深度【简单】

2023每日刷题&#xff08;六&#xff09; Leetcode—104.二叉树的最大深度 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int maxDepth(struct TreeNode* root){…

2017年高热度编程语言简介

世上语言千千万&#xff0c;我却独爱这一种!”这句话用来形容程序员和编程语言之间的爱恨情仇实在是再精准不过了。根据GitHub 2016年的开源报告&#xff0c;其上所有开源项目共包含了316种编程语言&#xff0c;这是一个什么概念呢?举个例子来说&#xff0c;世界上共有226个国…

高防CDN的发展趋势

随着互联网的迅速发展&#xff0c;网站和在线服务的安全性变得至关重要。网络攻击如DDoS攻击和恶意流量正在增加&#xff0c;因此高防CDN&#xff08;高防御内容分发网络&#xff09;成为网络安全的重要组成部分。本文将探讨高防CDN未来的发展趋势&#xff0c;并比较其与传统CD…

PyCharm改变代码背景图片的使用教程

一个好的集成环境是学习和使用一门编程语言的重中之重&#xff0c;这次我给大家分享如何改变PyCharm软件的代码背景图片。 说明&#xff1a;本教程使用的是汉化版PyCharm软件。 打开PyCharm软件。 点击软件最上方导航栏的文件&#xff0c;然后找到设置。 打开设置然后点击外观…

小米妙享无法正常启动,用非管理员权限启动

网上找到的其他方法大多数不太好 1.非管理员方式运行的方法 1.创建一个用户123&#xff0c;密码123 2.创建一个bat文件&#xff0c;复制粘贴以下内容 runas /savecred /user:123 “C:\Program Files\MI\AIoT\Launch.exe” 第一次点击运行&#xff0c;要输入密码&#xff0c;以…

面试官:说说webpack的热更新是如何做到的?

一、是什么 HMR 全称 Hot Module Replacement&#xff0c;可以理解为模块热替换&#xff0c;指在应用程序运行过程中&#xff0c;替换、添加、删除模块&#xff0c;而无需重新刷新整个应用 例如&#xff0c;我们在应用运行过程中修改了某个模块&#xff0c;通过自动刷新会导致…

靶机 DC_1

DC_1 信息搜集 存活检测 详细扫描 网页目录扫描 网页信息搜集 cms 为 Drupal 漏洞利用 使用 msf 搜索 drupal 的漏洞 启动 msfconsole搜索 search drupal尝试编号为 0 的漏洞 失败 利用编号为 1 的漏洞 use 1查看需要配置的选项 show options设置目标 ip set rhost 10…

Leetcode—1726.同积元组【中等】

2023每日刷题&#xff08;六&#xff09; Leetcode—1726.同积元组 哈希表解题思路 实现代码 class Solution { public:int tupleSameProduct(vector<int>& nums) {unordered_map<int, int>count;int n nums.size();int i, j;for(i 0; i < n - 1; i) {f…

C语言实现单链表(图解增删查改+代码)

文章目录 写在前面1. 链表节点的定义2. 链表的创建3. 插入数据3.1 头插3.2 尾插3.3 在指定位置的前面插入数据 4. 删除数据4.1 头删4.2 尾删4.3 删除指定位置的数据 5. 查找数据5. 链表的销毁 写在前面 上面文章用C语言实现了顺序表的增删查改&#xff0c;本片文章继续用C语言…

web各个指标理解

QPS : 单位时间得请求次数 TPS &#xff1a;单位时间得事务数 并发 &#xff1a; QPS *单位响应时间 pv &#xff1a;进入一个网站&#xff0c;又单击打开该网站的其他页面&#xff0c;每打开一个页面就 增加一个PV,甚至在同一页面每刷新一次也多一个PV 二八定律&#xff1a;百…

nonaDlA 逻辑分析仪 使用记录

注意事项&#xff0c;很灵敏&#xff0c;不要用手碰&#xff0c;产生误触发 安装软件 github地址 官方提供的淘宝地址与使用说明 1.安装 1.安装程序 &#xff1a;下载githubDLA源码&#xff0c;打开 software\PulseView.exe安装 2.安装驱动&#xff1a;安装完第一步后&a…

【OpenVINO】行人摔倒检测 — 基于 OpenVINO C# API 部署PP-Human-下篇

行人摔倒检测 — 基于 OpenVINO C# API 部署PP-Human 4. 配置 PP-Human_Fall_Detection 项目4.1 环境配置4.2 创建 AlxBoard_deploy_yolov8 项目4.3 添加项目源码4.4 添加 OpenVINO C# API4.5 添加 OpenCvSharp 5. 测试 PP-Human_Fall_Detection 项目5.1 创建视频读取器5.2 行人…

Python南瓜头

系列文章 ​​​​​​​ 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮…