c++中如何实现迪杰斯特拉算法_c++ Dijkstra最短路径算法详解
技术百科
尼克
发布时间:2026-01-21
浏览: 次 std::priority_queue不支持堆内元素修改,更新距离后需push新节点并跳过过时条目;邻接表推荐vector;Dijkstra不适用于负权边,应改用Bellman-Ford或SPFA。
用 std::priority_queue 实现 Dijkstra 时为什么距离更新后队列不自动排序
因为 std::priority_queue 不支持堆内元素修改,插入后无法调整位置。常见错误是:发现更短距离时直接 push 新节点,却不标记旧节点失效——导致后续重复处理过时的高代价路径。
- 必须配合一个
dist[]数组实时记录当前已知最短距离 - 每次从堆中
pop出节点时,先检查dist[u] != 当前弹出的距离,若不等说明已过时,直接跳过 - 不要尝试用
make_heap手动重排队列——开销大且易错
邻接表建图该用 vector> 还是 vector>>
推荐后者:vector,其中 graph[u] 存储所有从 u 出发的边,pair 表示 {v, weight}(终点与权重)。
- 前者(单个
vector)只能表达全局边集,无法快速枚举某点的邻接点,Dijkstra 中每轮需遍历所有边,时间退化为
O(EV) - 后者支持
O(degree(u))遍历邻居,总复杂度保持O((V + E) log V) - 若图稀疏(
E ≈ V),空间也更紧凑;稠密图可考虑邻接矩阵,但仅限V
遇到负权边就崩?不是说 Dijkstra 不能处理负权吗
是的,标准 Dijkstra 在存在负权边时结果不可靠——它依赖“已确定最短距的节点不会再被更新”这一前提,而负权边会破坏该性质。
- 若你发现算法输出路径比实际长,或
dist[v]在后期又被更小值覆盖,大概率是输入含负权边 - 此时应换用
Bellman-Ford(支持负权、可检测负环)或SPFA(Bellman-Ford 的队列优化版) - 注意:负权环存在时,最短路无定义;Dijkstra 对此完全无感知,也不会报错,只会静默给出错误结果
C++ 完整可运行的 Dijkstra 实现(带注释)
#include#include #include #include using namespace std; struct Edge { int to, w; }; vector dijkstra(int n, const vector >& graph, int start) { vector dist(n, LLONG_MAX); dist[start] = 0; // 小顶堆:{距离, 节点} priority_queue , vector >, greater >& pq; pq.push({0, start}); while (!pq.empty()) { auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue; // 过时条目,跳过 for (auto& e : graph[u]) { int v = e.to; long long new_dist = dist[u] + e.w; if (new_dist < dist[v]) { dist[v] = new_dist; pq.push({new_dist, v}); } } } return dist; } int main() { int n = 4, m = 5, s = 0; vector > graph(n); // 添加边:u->v 权重 w graph[0].push_back({1, 1}); graph[0].push_back({2, 4}); graph[1].push_back({2, 2}); graph[1].push_back({3, 6}); graph[2].push_back({3, 3}); auto res = dijkstra(n, graph, s); for (int i = 0; i < n; ++i) cout << "dist[" << i << "] = " << res[i] << "\n"; }
注意 dist 类型用 long long 防止松弛时溢出;LLONG_MAX 是初始化哨兵值,比较时别用 == 判未访问——应统一用 或 > 比较距离大小。图中节点编号从 0 开始是多数竞赛和库的默认习惯,别在索引上 off-by-one。
# ai
# 也不
# 这一
# 跳过
# 是说
# 弹出
# 只会
# 不支持
# edge
# 堆
# c++
# int
# stream
# 报错
# 为什么
# 算法
# ios
# 遍历
# 最短
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- PythonFastAPI项目实战教程_API接口
- 如何使用Golang开发基础文件下载功能_Gola
- windows系统找不到无线网络怎么办_windo
- 短链接怎么自定义还原php_修改解码规则适配需求【
- php下载安装后swoole扩展怎么安装_异步框架
- Python实现图数据库操作_Neo4j核心CRU
- Python邮件系统自动化教程_批量发送解析与模板
- 如何使用Golang实现路由参数绑定_使用Mux和
- Python项目回滚策略_发布安全说明【指导】
- php转exe用什么工具打包快_高效打包软件推荐【
- Win10怎样卸载TeamViewer_Win10
- Windows10如何更改鼠标图标_Win10鼠标
- Windows 10怎么隐藏特定更新补丁_Wind
- Go语言中slice追加操作的底层共享机制解析
- Python正则表达式实战_模式匹配说明【教程】
- 如何使用Golang table-driven基准
- Win11怎么自动隐藏任务栏_Win11全屏显示设
- Win11怎么开启智能存储_Windows11存储
- Win11怎样安装钉钉客户端_Win11安装钉钉教
- php中常量能用::访问吗_类常量与作用域操作符使
- php485在macos下怎么配置_php485
- Bpmn 2.0的XML文件怎么画流程图
- c++ nullptr与NULL区别_c++11空
- Win11怎么设置系统还原_Windows11系统
- php嵌入式日志记录怎么实现_php将硬件数据写入
- 如何高效识别并拦截拼接式恶意域名 spam
- Win11键盘快捷键大全_Windows 11常用
- C++中的协变与逆变是什么?C++函数指针与返回类
- Win11怎么设置默认浏览器Chrome_Wind
- Win10如何更改开机密码_Windows10登录
- 一文教你快速开通网站LOGO图
- 如何使用Golang包导出规则_控制函数和变量可见
- 如何在 Go 中可靠地测试含 time.Time
- Win11怎么关闭透明效果_Windows11个性
- Python随机数生成_random模块说明【指导
- C++中的Pimpl idiom是什么,有什么好处
- Win11怎么快速锁屏_Win11一键锁屏快捷键W
- Windows10怎样连接蓝牙设备_Windows
- Windows10怎么查看系统激活状态_Windo
- Windows怎样关闭Edge新标签页广告_Win
- C#怎么使用委托和事件 C# delegate与e
- Win11怎么查看局域网电脑_Windows 11
- Win10 BitLocker加密教程 Win10
- C#怎么创建控制台应用 C# Console Ap
- Win11如何隐藏桌面图标 Win11一键隐藏/显
- Win11怎么清理C盘虚拟内存_Win11清理虚拟
- Win11怎么打开注册表_Windows 11注册
- Win11怎么开启窗口对齐助手_Windows11
- Win10如何卸载微软拼音输入法 Win10只保留
- 如何在Golang中理解指针比较_Golang地址


QQ客服