std::priority_queue默认为最大堆,需用std::greater或自定义比较器(如a.first>b.first)实现最小堆;因不支持降键操作,必须采用懒删除:弹出时检查d==dist[u],否则跳过;邻接表用vector,dist数组初始化为llong_max或0x3f3f3f3f。

std::priority_queue的比较函数必须反向定义
迪杰斯特拉算法要求每次取出当前距离最小的节点,但std::priority_queue默认是大顶堆(最大值在顶部),直接用std::greater<int></int>或自定义operator容易搞反逻辑。常见错误是写成<code>dist[u] ,结果弹出的是最大距离节点,算法立刻失效。
正确做法是让优先队列按dist[u] > dist[v]排序——即“距离小的优先级高”。最稳妥的方式是用std::greater<:pair int>></:pair>配合std::pair<distance node></distance>,或者自定义仿函数返回a.first > b.first:
struct cmp {
bool operator()(const std::pair<int int>& a, const std::pair<int int>& b) {
return a.first > b.first; // 注意:> 表示小根堆
}
};
std::priority_queue<:pair int>, std::vector<:pair int>>, cmp> pq;</:pair></:pair></int></int>
不能用pq.top()更新已入队但距离变短的节点
std::priority_queue不支持修改队列中已有元素的值,也不支持删除中间节点。当某个节点的最短距离被更新时,只能把新距离的副本再次入队,旧副本留在队列里——这会导致重复处理。
解决方法是懒删除:每次pq.pop()后,检查dist[node]是否仍等于当前弹出的距离值。如果不等,说明已被更优路径更新过,直接跳过:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 入队时不检查是否已存在,只保证
dist[v] > dist[u] + w时才推入{dist[v], v} - 出队时加判断:
if (d != dist[u]) continue; - 这样虽然队列可能含冗余节点,但时间复杂度仍是
O((V+E) log E),且实现简洁
邻接表存储必须用vector>>
图结构推荐用std::vector<:vector int>>></:vector>,其中pair<weight to_node></weight>。别用map或unordered_map存邻接关系——它们的遍历开销大,且无法保证顺序无关性;也别把weight和to_node拆成两个容器,会增加索引同步成本。
初始化时注意索引从0还是1开始。如果节点编号是1~n,邻接表大小应为n+1,避免访问越界:
int n = 5; vector<vector int>>> graph(n + 1); // graph[1] ~ graph[5]有效 graph[1].emplace_back(2, 3); // 边 1→3 权重2</vector>
初始化dist数组要设为INT_MAX而非-1
用-1标记未访问会和距离为负数冲突(虽然迪杰斯特拉本身不支持负权边,但防御性编程建议统一用极大值)。std::numeric_limits<int>::max()</int>或INT_MAX更安全。
但要注意:如果后续做dist[u] + w可能溢出。稳妥做法是用long long类型存距离,或加溢出检查:
if (dist[u] == LLONG_MAX) continue;if (dist[u] + w- 起点
dist[src] = 0必须在入队前设置,否则会被忽略
if (d != dist[u]) continue;——漏掉它,算法就退化成暴力搜索,还可能算错结果。另外,std::priority_queue的模板参数顺序容易写错:第三个参数是比较器类型,不是实例,别传cmp()。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










