当前位置: 首页 > news >正文

C++ dijkstra 最短路径算法

一:概述      

        Dijkstra 算法是由 荷兰计算机科学家 Edsger W. Dijkstra(艾兹赫尔·戴克斯特拉) 在 1956 年 发明的,并于 1959 年正式发表。Dijkstra 算法 是一种用于计算图中 单源最短路径(Single-Source Shortest Path) 的经典算法。也就是说,它可以求出从一个起点到图中所有其他点的最短路径。

        Dijkstra 算法的核心思想是:贪心策略 —— 每次总是选择当前已知的距离起点最近的未访问节点,并尝试更新其邻居的最短路径。 

        

     算法步骤(以邻接表 + 最小堆实现为例):

  1. 初始化所有点到源点的距离为 ∞(无穷大),源点到自身为 0;

  2. 使用 最小堆(优先队列) 选择当前距离源点最短的节点;

  3. 对其所有邻居节点尝试 “松弛”操作(即更新邻居最短路径);

  4. 将更新后的节点重新加入堆中;

  5. 重复步骤 2~4,直到所有点都被访问或目标点被访问;

  6. 返回目标点的距离。

二:实现

#include <cassert>
#include <iostream>
#include <limits>
#include <queue>
#include <utility>
#include <vector>constexpr int64_t MAX = std::numeric_limits<int64_t>::max();namespace graph {using adjacency_list = std::vector<std::vector<std::pair<int, int>>>;/*** @brief 向图中添加一条有向边* @param adj 图的邻接表* @param u 起点编号(1-based)* @param v 终点编号(1-based)* @param w 边的权重*/void add_edge(adjacency_list& adj, int u, int v, int w) {adj[u - 1].emplace_back(v - 1, w);}/*** @brief 使用 Dijkstra 算法计算起点 s 到终点 t 的最短路径长度* @param adj 图的邻接表* @param s 起点编号(0-based)* @param t 终点编号(0-based)* @return 最短路径长度;不可达时返回 -1*/int dijkstra(const adjacency_list& adj, int s, int t) {int n = static_cast<int>(adj.size());std::vector<int64_t> dist(n, MAX);// 优先级队列(最小堆):元素为 pair<距离, 顶点编号>std::priority_queue<std::pair<int64_t, int>,std::vector<std::pair<int64_t, int>>,std::greater<>>pq;dist[s] = 0;pq.emplace(0, s);while (!pq.empty()) {auto [current_dist, u] = pq.top();pq.pop();// 如果当前距离大于已知距离,说明此条路径已过时,跳过if (current_dist > dist[u]) continue;// 松弛操作for (const auto& [v, weight] : adj[u]) {if (current_dist + weight < dist[v]) {dist[v] = current_dist + weight;pq.emplace(dist[v], v);}}}return dist[t] == MAX ? -1 : static_cast<int>(dist[t]);}/*** @brief 内置测试函数*/int run_tests() {std::cout << "Running predefined tests...\n";{std::cout << "Test 1...\n";adjacency_list adj(5);add_edge(adj, 1, 2, 3);add_edge(adj, 1, 3, 8);add_edge(adj, 2, 4, 2);add_edge(adj, 3, 5, 10);add_edge(adj, 4, 5, 1);assert(dijkstra(adj, 0, 4) == 6);  // 1->2->4->5 总权重 3+2+1=6std::cout << "Test 1 passed.\n";}{std::cout << "Test 2...\n";adjacency_list adj(4);add_edge(adj, 1, 2, 1);add_edge(adj, 2, 3, 4);add_edge(adj, 3, 4, 1);add_edge(adj, 1, 4, 10);assert(dijkstra(adj, 0, 3) == 6);  // 1->2->3->4 总权重 1+4+1=6std::cout << "Test 2 passed.\n";}{std::cout << "Test 3 (Unreachable)...\n";adjacency_list adj(3);add_edge(adj, 1, 2, 5);// 3号节点孤立,无法到达assert(dijkstra(adj, 0, 2) == -1);  // 1->3 不可达std::cout << "Test 3 passed.\n";}std::cout << "All tests passed successfully.\n";return 0;}}  // namespace graph

http://www.dtcms.com/a/269791.html

相关文章:

  • c语言学习_函数递归
  • 数学建模:非线性规划:凸规划问题
  • 【AI智能体】智能音视频-基于乐鑫 ESP32 实现音视频通话
  • ICML 2025 | TimeBridge : 巧妙化解非平稳性难题,精准预测长短结合!
  • Redis:高性能内存数据库与缓存利器
  • 验证KANO问题时合适的行为指标(如点击率、转化率等)来匹配问卷目标的一些尝试
  • 【论文翻译】用于大感受野的小波卷积 Wavelet Convolutions for Large Receptive Fields
  • 一天一道Sql题(day01)
  • Java武林:虚拟机之道 第二章:心法传承 - 类加载机制
  • three案例 Three.js波纹效果演示
  • “Jmeter中 xxx.jtl:1:1: Fatal Error! 前言中不允许有内容”的解决办法
  • 开源 SIP 协议栈介绍
  • INNER JOIN, LEFT JOIN, RIGHT JOIN 的区别
  • 字节面试被问到“手机号存储选 Int 还是 String”!
  • 区块链技术促进算力生态发展的具体案例
  • Python 机器学习核心入门与实战进阶 Day 6 - 模型保存与加载(joblib / pickle)
  • 2025年Linux安装MySQL详细教程
  • mysql-笔记
  • 服务器经常出现蓝屏是什么原因导致的?如何排查和修复?
  • Nature子刊:EPFL-ANU团队实现晶格对称性编程手性,双通道光学加密动态范围创1.6新高
  • Element-Plus-全局自动引入图标组件,无需每次import
  • 集群与集群应用
  • 东南亚主播解决方案|东南亚 TikTok 直播专线:纯净住宅 IP 、直播不卡顿
  • Spring自动装配(xml)
  • 芯片之后,AI之争的下一个战场是能源?
  • 小架构step系列08:logback.xml的配置
  • 知识库中如何确实嵌入文本块大小?语义完整性与检索颗粒度的平衡机制
  • 聊一聊软件架构师
  • C++排序算法全解析(加强版)
  • 单调栈通关指南:从力扣 84 到力扣 42