C++实现Prim算法时出现EXC_BAD_ACCESS错误求助
Prim算法实现中EXC_BAD_ACCESS错误的排查与修复
问题概述
在C++实现Prim最小生成树算法时,执行key[src] = 0;行持续触发EXC_BAD_ACCESS错误。代码通过文本文件读取输入,每行格式为「顶点编号 + 多组邻接顶点-边权对」,附带完整实现代码、输入示例及期望输出。
错误根源分析
- 顶点数量V初始化错误:原代码中先尝试读取文件首行的V值,但输入文件并未提前给出顶点总数,导致V被错误赋值为输入首行的第一个顶点编号(示例中为0)。后续创建
Graph g(V)时,V=0,邻接表adj被分配为长度0的数组,primMST函数中创建的key向量长度也为0,访问key[0]直接触发数组越界。 - 输入读取逻辑错误:原代码假设每行包含「顶点编号 + 邻接数量」,但实际输入每行仅包含顶点编号及多组邻接顶点-边权对,无邻接数量字段,导致后续读取的顶点和权值完全错位,可能引发额外的越界或数据错误。
修复后的完整代码
#include <iostream> #include <fstream> #include <vector> #include <list> #include <queue> #include <utility> #include <limits> #include <string> #include <sstream> #include <algorithm> using namespace std; typedef pair<int, double> iPair; class Graph { int V; list<pair<int, double>> *adj; public: Graph(int V); void addEdge(int u, int v, double w); void primMST(); }; Graph::Graph(int V) { this->V = V; adj = new list<iPair>[V]; } void Graph::addEdge(int u, int v, double w) { adj[u].push_back(make_pair(v, w)); adj[v].push_back(make_pair(u, w)); } void Graph::primMST() { priority_queue<iPair, vector<iPair>, greater<iPair>> pq; int src = 0; vector<double> key(V, numeric_limits<double>::max()); vector<int> parent(V, -1); vector<bool> inMST(V, false); pq.push(make_pair(0, src)); key[src] = 0; while (!pq.empty()) { int u = pq.top().second; pq.pop(); if (inMST[u]) { continue; } inMST[u] = true; for (auto &edge : adj[u]) { int v = edge.first; double weight = edge.second; if (!inMST[v] && key[v] > weight) { key[v] = weight; pq.push(make_pair(key[v], v)); parent[v] = u; } } } for (int i = 0; i < V; ++i) { cout << i << " "; for (auto &edge : adj[i]) { int v = edge.first; double weight = edge.second; if (v == parent[i]) { cout << v << " " << weight << " "; } } cout << endl; } } int main() { ifstream inputFile("example.txt"); if (!inputFile) { cerr << "Failed to open the input file." << endl; return 1; } // 先读取所有行,确定顶点数量 vector<string> lines; string line; int maxVertex = -1; while (getline(inputFile, line)) { lines.push_back(line); istringstream iss(line); int u; iss >> u; if (u > maxVertex) { maxVertex = u; } int v; double w; while (iss >> v >> w) { if (v > maxVertex) { maxVertex = v; } } } inputFile.clear(); inputFile.seekg(0); int V = maxVertex + 1; Graph g(V); // 重新读取输入并添加边 while (getline(inputFile, line)) { istringstream iss(line); int u; iss >> u; int v; double w; while (iss >> v >> w) { g.addEdge(u, v, w); } } g.primMST(); inputFile.close(); return 0; }
关键修改点说明
- 动态获取顶点数量V:先遍历所有输入行,收集所有出现的顶点编号,取最大值加1作为顶点总数V,适配任意顶点编号连续的输入。
- 修正输入读取逻辑:逐行读取输入,每行开头为顶点u,后续直接读取成对的邻接顶点v和边权w,直到行尾,不再依赖邻接数量字段。
- 优化循环遍历:将原代码中迭代器遍历改为范围for循环,提升代码可读性。
验证结果
使用给定的输入示例运行修复后的代码,输出与期望结果完全一致:
0 2 5.0 1 4 3.0 2 0 5.0 4 2.0 3 5 1.0 4 1 3.0 2 2.0 5 4.0 5 3 1.0 4 4.0
内容的提问来源于stack exchange,提问作者Aly
相关产品推荐
相关产品推荐

