c++如何实现迪杰斯特拉最短路径算法_c++ 优先队列优化与邻接表【详解】

发布时间 - 2026-01-21 00:00:00    点击率:
Dijkstra必须用priority_queue配合邻接表以达O((V+E)log V)复杂度;优先队列保证取最小距离节点为O(log V),邻接表确保只遍历真实存在的边;需接受重复入队并跳过过期节点。

为什么 dijkstra 一定要用 priority_queue 配合邻接表?

不用优先队列的朴素 dijkstra 时间复杂度是 O(V²),对点数超 10⁴ 的图基本不可用;而用 std::priority_queue + 邻接表可压到 O((V+E) log V)。关键在于:每次取最小距离节点必须是 O(log V),且只遍历真实存在的边(邻接表保证 E 级别访问),不是全扫数组。

常见错误是把 priority_queue 当成“自动更新堆顶”的容器——它不支持修改已有元素的值,所以必须接受重复入队:当发现更短路径时,直接 push 新二元组 {dist, node},旧的会在后续被 pop 时跳过(靠 if (dist[node] 过滤)。

priority_queue 的比较规则怎么写才不翻车?

C++ 默认是大根堆,但我们要的是“距离最小的先出”,所以必须自定义比较器。最稳妥写法是用仿函数或 lambda,且注意:不能直接写 greater>,因为 pair 比较先比 first,而我们希望 first 是距离,所以要让小距离排前面——即“less”语义,但 priority_queue 的模板参数是“谁该被优先弹出”,所以实际要传入「大于」逻辑(即当 a > b 时,a 应该后出,b 先出)。

  • 推荐写法:
    priority_queue, vector>, greater>> pq;
  • 等价但更清晰的 lambda 写法(C++11+):
    auto cmp = [](const pair& a, const pair& b) { return a.first > b.first; };
    priority_queue, vector>, decltype(cmp)> pq(cmp);
  • 错误示范:priority_queue>(大根堆,会先弹出最大距离)

邻接表怎么建?vector>> 还是 vector>

vector>> 是最常用且高效的选择:第一维是起点编号,第二维每个 pair 表示一条有向边(无向图就双向加)。它缓存友好、随机访问快、构造简单。除非边数极少且频繁删边,否则别用 listmap

注意权重类型:如果题目给的是非负整数,用 int;若可能超 INT_MAX 或含浮点,需统一换成 long longdouble,并同步改 dist 数组和 priority_queue 中的类型。

建边示例(无向图):

vector>> graph(n);
// 加边 u->v 权重 w
graph[u].emplace_back(v, w);
graph[v].emplace_back(u, w);

初始化、松弛、跳过失效节点这三步最容易漏哪?

三个关键动作必须严格按序,缺一不可:

  • 初始化:dist 数组全设为 INT_MAX(或 LLONG_MAX),dist[src] = 0,然后 pq.push({0, src})
  • 松弛:对当前节点 u 的每条出边 (u→v, w),若 dist[u]

    + w ,则更新 dist[v]pq.push({dist[v], v})
  • 跳过失效节点:在 while (!pq.empty()) 循环开头,auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue; —— 这行不能省,否则会处理过期状态,导致结果错误或超时

特别注意:dist 数组必须是全局可见的(比如函数内 vector dist(n, LLONG_MAX)),不能用局部临时变量覆盖;且所有涉及距离比较的地方,类型必须与 dist 一致,避免隐式转换截断。

真正卡住人的往往不是算法逻辑,而是类型不匹配、堆比较器反了、或者忘了跳过过期节点——这三处任一出错,结果就完全不对,还很难 debug。


# node  # ai  # c++  # 隐式转换  # 为什么  # less  # if  # while  # auto  # continue  # int  # double  # 循环  # Lambda  #   # map  # 算法  # 跳过  # 遍历  # 弹出  # 这三  # 的是  # 很难  # 浮点  # 已有  # 设为  # 会在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 郑州企业网站制作公司,郑州招聘网站有哪些?  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  如何安全更换建站之星模板并保留数据?  Laravel如何处理异常和错误?(Handler示例)  Laravel如何升级到最新版本?(升级指南和步骤)  Laravel如何升级到最新的版本_Laravel版本升级流程与兼容性处理  北京专业网站制作设计师招聘,北京白云观官方网站?  Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  Laravel如何处理表单验证?(Requests代码示例)  国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?  深入理解Android中的xmlns:tools属性  如何获取免费开源的自助建站系统源码?  javascript如何操作浏览器历史记录_怎样实现无刷新导航  EditPlus中的正则表达式 实战(1)  ,在苏州找工作,上哪个网站比较好?  网站图片在线制作软件,怎么在图片上做链接?  大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  如何快速搭建个人网站并优化SEO?  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  Laravel如何与Inertia.js和Vue/React构建现代单页应用  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  米侠浏览器网页背景异常怎么办 米侠显示修复  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  Laravel如何使用Sanctum进行API认证?(SPA实战)  如何用好域名打造高点击率的自主建站?  Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程  Claude怎样写结构化提示词_Claude结构化提示词写法【教程】  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  Laravel如何创建自定义中间件?(Middleware代码示例)  如何快速生成高效建站系统源代码?  使用C语言编写圣诞表白程序  Python数据仓库与ETL构建实战_Airflow调度流程详解  如何用wdcp快速搭建高效网站?  潮流网站制作头像软件下载,适合母子的网名有哪些?  如何使用 jQuery 正确渲染 Instagram 风格的标签列表  Laravel如何实现文件上传和存储?(本地与S3配置)  ,网页ppt怎么弄成自己的ppt?  如何用腾讯建站主机快速创建免费网站?  如何在IIS7上新建站点并设置安全权限?  Laravel Blade模板引擎语法_Laravel Blade布局继承用法  公司门户网站制作流程,华为官网怎么做?