调用Dijkstra函数后C++程序无输出,主函数执行异常求助
看起来你的程序遇到了栈溢出的问题,这也是调用dijkstra函数后无输出、主函数后续代码停止执行的核心原因。让我一步步拆解问题并给出修复方案:
1. 核心问题:结构体值传递导致栈溢出
你的mygragh结构体里包含了一个int map[1000][1000]的二维数组,这个数组大小是1000*1000*4 = 4,000,000字节(约4MB)。当你以值传递的方式把g传给dijkstra函数时,程序会在栈上完整拷贝这个4MB的数组。而大多数操作系统的默认栈空间只有1~8MB,这么大的拷贝直接撑爆了栈,导致程序异常终止——连dijkstra里的cout << "called dijkstra\n";都来不及执行,更别说主函数后续的代码了。
修复方案:改用引用传递
把dijkstra的函数参数改成引用,避免拷贝整个庞大的结构体:
void dijkstra(mygragh& g, int dis[], int pre[], int v0) { // 函数内容不变 }
这样只会传递结构体的地址,不会拷贝数组,彻底解决栈溢出问题。
2. 其他潜在问题与修复
除了核心的栈溢出,你的代码还有几个需要修正的地方,否则即使解决了栈溢出,程序也可能运行异常:
(1) 未包含INT_MAX的头文件
INT_MAX定义在<climits>头文件中,你的代码没有包含它,属于未定义行为,有些编译器可能会报错或出现奇怪的数值。在代码开头添加:
#include <climits>
(2) 非标准的变长数组
C标准并不支持int dis[n];这种变长数组(这是C99的特性,部分编译器如GCC会支持,但不是跨平台的)。改用vector来动态创建数组更符合C规范:
// 替换原来的int dis[n]; int pre[n]; vector<int> dis(n); vector<int> pre(n);
同时建议把dijkstra函数的参数改成引用(比指针更安全):
void dijkstra(mygragh& g, vector<int>& dis, vector<int>& pre, int v0) { int n = g.n; vector<bool> visit(n, false); for (int i = 0; i < n; i++) { if (g.map[v0][i] != INT_MAX) { dis[i] = g.map[v0][i]; pre[i] = v0; } else { dis[i] = INT_MAX; pre[i] = -1; } } // 后续代码不变 }
(3) 图初始化逻辑不一致
你注释掉了fill(g.map, g.map + n * n, INT_MAX);,改用了g.map[i][j] = 100;,但dijkstra函数里仍然判断g.map[v0][i] != INT_MAX,这会导致逻辑错误——因为你的边权值可能小于100,而初始化的100会被当成有效的边权,而不是“不可达”的标记。
恢复fill的代码(记得包含<algorithm>头文件,因为fill在里面),这样才能正确初始化所有边为“不可达”:
#include <algorithm> // 添加这个头文件 // 在初始化map的地方: fill(g.map[0], g.map[0] + n * n, INT_MAX); // 二维数组首地址用g.map[0]更准确 for (int i = 0; i < n; i++) { g.map[i][i] = 0; }
(4) 避免整数溢出
在dijkstra的松弛操作中,添加g.map[u][j] != INT_MAX的判断,防止dis[u] + g.map[u][j]溢出:
if (!visit[j] && g.map[u][j] != INT_MAX && dis[j] > dis[u] + g.map[u][j]) { dis[j] = dis[u] + g.map[u][j]; pre[j] = u; }
修复后的完整代码示例
整合所有修改后的代码如下:
#include <iostream> #include <vector> #include <climits> #include <algorithm> using namespace std; struct mygragh { int map[1000][1000]; int e; int n; }; void dijkstra(mygragh& g, vector<int>& dis, vector<int>& pre, int v0) { cout << "called dijkstra\n"; int n = g.n; vector<bool> visit(n, false); for (int i = 0; i < n; i++) { if (g.map[v0][i] != INT_MAX) { dis[i] = g.map[v0][i]; pre[i] = v0; } else { dis[i] = INT_MAX; pre[i] = -1; } } visit[v0] = true; for (int i = 0; i < n; i++) { int min_val = INT_MAX, u = -1; for (int j = 0; j < n; j++) { if (!visit[j] && dis[j] < min_val) { min_val = dis[j]; u = j; } } if (u == -1) { break; } visit[u] = true; for (int j = 0; j < n; j++) { if (!visit[j] && g.map[u][j] != INT_MAX && dis[j] > dis[u] + g.map[u][j]) { dis[j] = dis[u] + g.map[u][j]; pre[j] = u; } } } } int main() { cout << "called main\n"; mygragh g; int n = 5; int e = 7; g.n = n; g.e = e; vector<int> dis(n); vector<int> pre(n); // 初始化图为不可达 fill(g.map[0], g.map[0] + n * n, INT_MAX); for (int i = 0; i < n; i++) { g.map[i][i] = 0; } cout << "请输入7条边的起点、终点和长度(节点编号0-4):\n"; for (int i = 0; i < e; i++) { int c1, c2, l; if (!(cin >> c1 >> c2 >> l)) { cerr << "输入无效,程序退出\n"; return 1; } // 确保节点编号合法 if (c1 < 0 || c1 >= n || c2 < 0 || c2 >= n) { cerr << "节点编号超出范围\n"; return 1; } g.map[c1][c2] = l; g.map[c2][c1] = l; } dijkstra(g, dis, pre, 0); cout << "节点0到节点1的最短路径长度:" << dis[1] << endl; return 0; }
验证效果
现在运行程序,你会看到:
- 首先输出
called main - 提示输入边信息
- 输入完成后,输出
called dijkstra - 最后输出节点0到节点1的最短路径长度
这样就解决了你遇到的所有问题。
内容的提问来源于stack exchange,提问作者Sherry Le

