0

0

C++怎么实现迪杰斯特拉算法_C++最短路径求解【路径】

尼克

尼克

发布时间:2026-03-02 11:39:11

|

575人浏览过

|

来源于php中文网

原创

dijkstra需最小堆,std::priority_queue默认最大堆,须用std::greater或自定义比较器;路径还原需prev[]数组,负权边不适用,多终点无需重复运行,字典序路径需松弛时额外比较。

c++怎么实现迪杰斯特拉算法_c++最短路径求解【路径】

std::priority_queue 实现 Dijkstra 时,为什么总是得不到正确路径?

因为默认的 std::priority_queue 是最大堆,而 Dijkstra 需要每次取当前距离最小的节点;不重载比较逻辑或换容器,top() 返回的就是错的节点。

  • 必须用 std::greater<:pair int>></:pair> 或自定义比较器,让优先队列按距离升序排列
  • 推荐写法:std::priority_queue<:pair int>, std::vector<:pair int>>, std::greater<:pair int>>></:pair></:pair></:pair>
  • 别把 distancenode_id 顺序写反——pair<dist node></dist> 才能靠 first 正确比较
  • 如果图稀疏但用了邻接矩阵,会超时;稠密图才适合矩阵,否则务必用邻接表(vector<vector int>>></vector>

如何还原最短路径,而不是只算出最短距离?

单纯更新 dist[] 数组只能知道长度,要路径就得记录前驱。Dijkstra 本身不天然支持路径回溯,得手动维护 prev[] 数组。

  • 初始化 prev[i] = -1,松弛成功时立即更新:prev[v] = u(u → v 是更优边)
  • 路径还原用栈或递归逆序输出,避免 vector insert(0, ...) 导致 O(n²) 复杂度
  • 注意:prev 只在松弛成功时更新,不是每次访问都改;重复入队的节点不会覆盖已确定的前驱
  • 如果起点到某点不可达,prev[end] 仍是 -1,别直接解引用

遇到负权边就崩,是算法写错了还是理解错了?

Dijkstra 从数学上就不支持负权边——一旦某个节点被标记为“已确定最短距离”,后续就不再检查,而负权边可能提供更短路径,导致结果错误。

凡科AI抠图
凡科AI抠图

简单好用的在线抠图工具

下载
  • 运行时不会报错,但输出距离明显偏大,或 prev 指向形成环(比如 A→B→A)
  • 确认图中是否存在负权边:读入边权重后加个断言 assert(w >= 0),调试阶段很有用
  • 真有负权且无负环,该换 Bellman-FordSPFA;有负环则最短路径无定义
  • 别试图“修复”Dijkstra 来处理负权——它不是 bug,是能力边界

多终点 / 路径唯一性 / 重建路径时内存爆炸怎么办?

原始 Dijkstra 是单源单终点思维,但实际常需查多个终点距离、或要求字典序最小路径、或图极大时存不下完整 prev 数组。

立即学习C++免费学习笔记(深入)”;

  • 多终点:跑一遍 Dijkstra 就够了,所有 dist[end_i] 都有效,不用反复调用
  • 字典序最小路径:松弛时加一层判断——距离相等时,比较 prev[u] 对应的路径字典序,但这要存整个路径串,代价高;更实用的是在松弛条件里加 || (dist[v] == dist[u] + w && prev[v] > u)
  • 内存受限:不用全局 prev[],改用“按需重建”——每个查询终点时,从该点倒推,用哈希表或临时数组存已访问过的前驱,避免存全部
  • 注意:prev 数组大小必须 ≥ 节点数,下标从 0 开始就别用 1-based 初始化漏掉 index 0
事情说清了就结束

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

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

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

430

2023.07.18

堆和栈区别
堆和栈区别

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

599

2023.08.10

堆和栈的区别
堆和栈的区别

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

430

2023.07.18

堆和栈区别
堆和栈区别

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

599

2023.08.10

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

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

483

2023.08.14

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

43

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

38

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

35

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

20

2026.02.27

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 10.5万人学习

C 教程
C 教程

共75课时 | 5.1万人学习

C++教程
C++教程

共115课时 | 20万人学习

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

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