C++实现Dijkstra算法触发request for member编译错误如何解决?
错误原因
核心问题是优先队列的元素类型声明与实际使用逻辑不匹配:
- 你声明的优先队列类型为
std::priority_queue<T, std::vector<T>, std::greater<T>>,本次编译时T被实例化为unsigned int,队列存储的是基础无符号整型变量,不存在你代码中调用的vertex_ID、distance_from_source自定义成员,因此编译器直接抛出成员访问错误。 - 同时你调用
heap.emplace(src, 0)给无符号整型传入两个构造参数本身也存在语法错误,只是编译器优先触发了成员访问类的报错。 - 额外隐藏问题:循环中
if (current_vertex == dest)的判断逻辑也和后续访问成员的逻辑冲突,即使类型声明正确也会报错,原代码还遗漏了源点距离初始化的逻辑,会导致距离计算结果异常。
修复方案
- 先自定义堆节点结构体,用来同时存储顶点ID和当前到源点的距离,重载比较运算符适配小顶堆排序逻辑
- 修改优先队列的类型声明为存储自定义堆节点
- 调整堆元素的比较逻辑匹配结构体成员,补全缺失的初始化逻辑
修改后的完整代码如下:
// 自定义堆节点结构体,需要写在dijkstra_shortest_path函数之前 template<typename T> struct HeapNode { size_t vertex_ID; T distance_from_source; // 重载大于运算符,适配std::greater实现小顶堆 bool operator>(const HeapNode& other) const { return distance_from_source > other.distance_from_source; } }; template<typename T> auto dijkstra_shortest_path(const Graph<T>& G, size_t src, size_t dest){ // 优先队列类型修改为存储HeapNode std::priority_queue<HeapNode<T>, std::vector<HeapNode<T>>, std::greater<HeapNode<T>>> heap; std::set<size_t> visited; // 同步修改为size_t避免类型不匹配 std::vector<size_t> parent(G.vertices()); std::vector<T> distance(G.vertices(), std::numeric_limits<T>::max()); std::vector<size_t> shortest_path; heap.emplace(src, 0); distance[src] = 0; // 补全源点距离初始化 parent[src] = src; while (!heap.empty()){ auto current_vertex = heap.top(); heap.pop(); // 改为判断顶点ID是否等于终点 if (current_vertex.vertex_ID == dest){ std::cout << "Destination " << current_vertex.vertex_ID << " reached." << std::endl; break; } if (visited.find(current_vertex.vertex_ID) == visited.end()) { std::cout << "Settling vertex " << current_vertex.vertex_ID << std::endl; for (auto e : G.outgoing_edges(current_vertex.vertex_ID)) { auto neighbor_vertex_ID = e.dest; auto new_distance_to_dest=current_vertex.distance_from_source + e.weight; if (new_distance_to_dest < distance[neighbor_vertex_ID]) { heap.emplace(neighbor_vertex_ID, new_distance_to_dest); parent[e.dest] = current_vertex.vertex_ID; distance[e.dest] = new_distance_to_dest; } } visited.insert(current_vertex.vertex_ID); } } auto current_vertex = dest; while (current_vertex != src) { shortest_path.push_back(current_vertex); current_vertex = parent[current_vertex]; } shortest_path.push_back(src); std::reverse(shortest_path.begin(), shortest_path.end()); return shortest_path; }
内容的提问来源于stack exchange,提问作者juanp_30
相关产品推荐
相关产品推荐

