邻接矩阵实现最宽路径问题:修改版Dijkstra路径打印异常排查
问题排查与修复方案
1. 路径打印异常问题根因
- previous数组初始化错误:现有代码仅将
previous[0] = -1,其余元素为内存随机值,导致printPath中previous[j] != -1的终止判断失效,无法输出中间节点。 - 路径输出顺序错误:现有
printPath从终点向起点遍历直接打印,输出的是倒序路径,和起点拼接后逻辑错误。 - 隐式声明异常:若
island.h中未对dijkstra_mod、printSolution等函数做前置声明,C语言会触发隐式声明规则,参数类型不匹配会导致printf输出异常值(如你提到的类地址值)。 - 节点输入范围校验错误:你的图大小为9,合法节点索引为0~8,现有代码判断
current_node >9、destination>10范围错误,且未做循环校验,输入非法值后仅提示一次就继续执行。
2. Dijkstra算法逻辑错误根因
你的需求是边权均大于卡车重量的前提下,找最大瓶颈路径(路径最小边权尽可能大)、瓶颈相同时选边数最少的路径,现有实现完全不符合需求:
- 松弛逻辑错误:最大瓶颈路径的权重计算不是边权累加,而是取路径上的最小边权。现有代码使用
sptWeight[u] + Graph[u][v]的累加逻辑完全错误,且初始化sptWeight为INT_MIN,累加值永远大于初始值,根本不会触发更新逻辑。 - 未过滤不可通行边:完全没有增加
Graph[u][v] > truck_weight的判断,会把不能承载卡车重量的边纳入路径计算。 - 未处理边数最少的优先级:相同瓶颈值下没有比较路径长度,无法保证输出边数最少的路径。
3. 修复后的核心代码
打印逻辑修复
// 递归打印保证路径顺序正确 void printPath(int previous[], int j){ if(previous[j] == -1) return; printPath(previous, previous[j]); printf("%d -> ", j); } void printSolution(int destination, int source, int previous[SIZE], int sptBottleneck[SIZE]){ if(sptBottleneck[destination] == INT_MIN){ printf("\n无符合载重要求的路径从 %d 到 %d\n", source, destination); return; } printf("\n%d 到 %d \t 最大瓶颈载重: %d\t 路径: %d -> ", source, destination, sptBottleneck[destination], source); printPath(previous, destination); printf("\n"); }
Dijkstra核心逻辑修复
// 没有min宏可以自己实现,避免引入额外依赖 #define min(a,b) ((a)<(b)?(a):(b)) void dijkstra_mod(int Graph[SIZE][SIZE], int source, int destination, int truck_weight){ int sptBottleneck[SIZE]; // 存储到每个节点的最大瓶颈值 int pathLen[SIZE]; // 存储到每个节点的路径边数,同瓶颈下选边数少的 bool sptSet[SIZE]; int previous[SIZE]; // 全数组初始化 for(int i = 0; i < SIZE; i++){ sptBottleneck[i] = INT_MIN; pathLen[i] = INT_MAX; sptSet[i] = false; previous[i] = -1; } sptBottleneck[source] = INT_MAX; // 起点瓶颈设为无穷大 pathLen[source] = 0; for(int count = 0; count < SIZE-1; count++){ int u = maxSupportWeight(sptBottleneck,sptSet); if(u == -1) break; // 无可达节点直接退出 sptSet[u] = true; for(int v = 0; v < SIZE; v++){ // 过滤未加入spt、边存在、边权满足载重要求的边 if(!sptSet[v] && Graph[u][v] && Graph[u][v] > truck_weight){ int new_bottleneck = min(sptBottleneck[u], Graph[u][v]); // 新路径瓶颈更大,直接更新 if(new_bottleneck > sptBottleneck[v]){ previous[v] = u; sptBottleneck[v] = new_bottleneck; pathLen[v] = pathLen[u] + 1; } // 瓶颈相同,新路径边数更少,更新 else if(new_bottleneck == sptBottleneck[v] && pathLen[u] + 1 < pathLen[v]){ previous[v] = u; pathLen[v] = pathLen[u] + 1; } } } } printSolution(destination, source, previous, sptBottleneck); }
节点输入校验修复(main.c中对应逻辑替换)
printf("Inserisci il nodo di partenza\n"); scanf("%d", ¤t_node); while(current_node < 0 || current_node >= SIZE){ printf("Nodo di partenza non riconosciuto,输入范围为0~%d,请重新输入:\n", SIZE-1); scanf("%d", ¤t_node); } printf("Inserisci la tua destinazione\n"); scanf("%d", &destination); while(destination < 0 || destination >= SIZE){ printf("Destinazione non riconosciuta,输入范围为0~%d,请重新输入:\n", SIZE-1); scanf("%d", &destination); }
额外注意:要在island.h中添加所有对外暴露函数的前置声明,避免隐式声明导致的参数解析异常。
内容的提问来源于stack exchange,提问作者Nicholas Marsicano
相关产品推荐
相关产品推荐

