0

0

最短路径问题是什么?Dijkstra算法实现

小老鼠

小老鼠

发布时间:2025-08-22 15:09:01

|

338人浏览过

|

来源于php中文网

原创

Dijkstra算法是解决最短路径问题的经典方法,适用于边权为正的图,通过贪心策略和优先级队列高效确定从起点到各节点的最短路径。

最短路径问题是什么?dijkstra算法实现

最短路径问题,简单来说,就是在给定网络或图中,找到从一个节点到另一个节点成本最低(或距离最短)的路径。而Dijkstra算法,正是解决这类问题的经典方法之一,它能有效地找出图中所有边权均为正数时的最短路径。它就像一个智能导航员,总能帮你找到最省钱或最省时的路线。

Dijkstra算法实现

Dijkstra算法的核心思想,其实是一种贪心策略:它总是选择当前已知最短路径的未访问节点进行扩展。听起来有点抽象?想象一下,你从家出发,想去几个朋友家拜访,每次都先去离你最近、且你还没去过的朋友家,然后看看从他家出发,能不能更近地到达其他朋友家。

具体实现上,我们需要维护几个关键信息:

  1. 距离数组 (dist[]):记录从起点到每个节点的当前最短距离。初始化时,起点为0,其他为无穷大。
  2. 访问状态 (visited[]):标记节点是否已经被“确定”了最短路径。
  3. 优先级队列 (priority_queue):存储 (距离, 节点) 对,每次取出距离最小的节点。

算法步骤概览:

  1. 将起点加入优先级队列,距离设为0。
  2. 当队列不为空时: a. 取出队列中距离最小的节点
    u
    。 b. 如果
    u
    已经被访问过,跳过。 c. 标记
    u
    为已访问。 d. 遍历
    u
    的所有邻居
    v
    : i. 如果
    u
    v
    的路径加上
    u
    的距离比当前
    v
    的距离更短,就更新
    v
    的距离,并将
    (新距离, v)
    加入优先级队列。
import heapq

def dijkstra(graph, start_node):
    # graph: 邻接列表表示,例如 {node: [(neighbor, weight), ...]}
    distances = {node: float('inf') for node in graph}
    distances[start_node] = 0

    priority_queue = [(0, start_node)] # (distance, node)

    # visited_nodes = set() # 也可以用这个,但通常在循环内部判断更高效

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

        # 如果当前距离比已记录的要大,说明我们已经找到了更短的路径,跳过
        # 这是为了处理优先级队列中可能存在的“过期”数据
        if current_distance > distances[current_node]:
            continue

        # 遍历当前节点的所有邻居
        for neighbor, weight in graph.get(current_node, []):
            distance = current_distance + weight

            # 如果通过当前节点到达邻居的路径更短
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(priority_queue, (distance, neighbor))

    return distances

# 示例用法
# graph_example = {
#     'A': [('B', 1), ('C', 4)],
#     'B': [('C', 2), ('D', 5)],
#     'C': [('D', 1)],
#     'D': []
# }
# shortest_paths = dijkstra(graph_example, 'A')
# print(shortest_paths) # {'A': 0, 'B': 1, 'C': 3, 'D': 4}

为什么最短路径问题如此重要?

我个人觉得,最短路径问题的重要性几乎渗透在我们日常生活的方方面面,只是我们很少意识到。你想想看,你打开手机导航,它瞬间给你规划出几条路线,还告诉你哪条最快——这背后就是最短路径算法在飞速运转。物流公司要优化配送路线,减少油耗和时间;网络数据包要在复杂的互联网中找到最快传输路径;甚至在游戏里,NPC角色怎么找到最快路径追击玩家,或者寻路去完成任务,都离不开它。

它不仅仅是理论上的一个算法,更是支撑现代社会高效运转的基石之一。没有它,我们现在习以为常的便利,比如即时送达的外卖、流畅的网络视频通话,可能都难以实现。在我看来,理解最短路径,某种程度上就是理解现代信息流和物流的底层逻辑。

Dijkstra算法的局限性:负权边怎么办?

Dijkstra算法确实非常高效,但它有一个核心前提:图中所有的边权都必须是非负数。如果你的图中存在负权边(比如,某条路径能让你“赚”到时间或资源,表现为负值),Dijkstra就会“失效”了。为什么呢?因为Dijkstra的贪心策略是基于“一旦一个节点的最短路径被确定,它就不会再被更新”这个假设的。但如果存在负权边,一个看似已经确定最短路径的节点,未来可能会通过一条包含负权边的路径,被进一步“缩短”。

AI智研社
AI智研社

AI智研社是一个专注于人工智能领域的综合性平台

下载

举个例子,你从A到B是5,从B到C是-10。Dijkstra可能先确定了A到B是5,然后去扩展B。但如果A到某个D是2,D到B是-100,那A到B的最短路径就不再是5了。Dijkstra的“一旦确定就不变”的机制,在这里就被打破了。

所以,如果你的图里有负权边,你就需要考虑其他的算法了,比如Bellman-Ford算法,它虽然效率不如Dijkstra,但能处理负权边,甚至能检测出负权环(一个会无限降低路径成本的循环)。

Dijkstra算法内部机制:优先级队列扮演了什么角色?

要说Dijkstra算法的“灵魂”,那非优先级队列莫属了。它在整个算法的运行中起到了至关重要的作用,就像一个智能调度中心。

回想一下,Dijkstra算法每次都要从所有未访问的节点中,找到当前距离起点最近的那个节点。如果每次都遍历所有未访问节点来找,那效率会非常低。优先级队列(通常用最小堆实现)就完美解决了这个问题。

每当我们发现一条从起点到某个节点

v
的更短路径时,我们就把
(新的距离, v)
这个对扔进优先级队列里。优先级队列的特性保证了,每次
heappop()
操作,都会把当前所有已知路径中,距离起点最近的那个节点和它的距离弹出来。这样,算法就能确保每次扩展的都是当前“最有可能”是最终最短路径的节点。

它避免了盲目探索,而是有策略地、一步步地“锁定”每个节点的最短路径。这种机制确保了算法的正确性,也大大提升了它的效率,尤其是在稀疏图(边数相对节点数较少)中表现尤为出色。可以说,没有优先级队列,Dijkstra算法的效率会大打折扣,甚至无法被称为一个“高效”的算法。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

398

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

414

2023.08.14

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

4

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

2

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

1

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

1

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

16

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

PHP面向对象基础课程(更新中)
PHP面向对象基础课程(更新中)

共12课时 | 0.7万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号