如何打印图两节点间所有路径开销并修复DFS回溯崩溃问题
问题根因
报错退出码0xC0000005对应内存访问违例,核心是回溯阶段的权重处理逻辑存在两处致命错误:
- 权重加减不配对:你在父节点遍历邻接边、递归进入子节点前累加了对应边的权重,但没有在递归返回后立刻做对应的扣减,反而试图在子节点的递归出口统一扣减权重。
- 扣减权重时的内存访问完全非法:
graph->distance -= graph->array[graph->index]->weight;这行代码存在本质错误:graph->array是邻接表数组,合法索引是节点ID,但你传入的graph->index是路径数组的长度计数器,不是节点ID,一旦数值超过节点总数、或对应位置的邻接表为空,就会触发数组越界/空指针解引用,直接导致程序崩溃。- 即使索引合法,取到的也是当前节点邻接表第一条边的权重,和之前累加的「父节点到当前节点的边权重」完全不匹配,就算不崩溃,路径总开销的计算结果也是错的。
修复方法
仅需两处改动即可解决所有问题:
- 删除递归函数末尾那行错误的权重扣减代码
- 将权重扣减逻辑移到邻接节点遍历循环内,递归调用返回后立刻扣减当前边的权重,和递归前的累加操作严格配对,保证谁加的谁负责减。
修复后可运行代码
// Find all paths from source to destination. void search(Graph* graph, int src, int dst) { // Mark the current node and store it in path. graph->visited[src] = true; graph->path[graph->index] = src; graph->index++; // If current vertex is same as destination. if (src == dst) { for (int i = 0; i < graph->index; i++) { if (i != graph->index - 1) { printf("%d -> ", graph->path[i] + 1); } else { printf("%d = %.3f\n\t", graph->path[i] + 1, graph->distance); } } } else { // For all unvisited vertices adjacent to current vertex. for (Node* adj = graph->array[src]; adj; adj = adj->next) { if (!graph->visited[adj->vertex]) { graph->distance += adj->weight; search(graph, adj->vertex, dst); // 递归返回后立刻扣减当前边权重,和累加操作严格配对 graph->distance -= adj->weight; } } } // Remove current vertex from path and mark it as unvisited. graph->index--; graph->visited[src] = false; }
说明
修复后回溯逻辑完全自洽:路径记录、访问标记的回溯逻辑保留,保证所有可达路径都能被遍历到;权重的累加和扣减严格跟随递归的进入和返回,总开销计算准确;不存在非法内存访问,不会再触发崩溃。运行后可完整输出预期的5条路径,程序正常退出。
内容的提问来源于stack exchange,提问作者Varnion
相关产品推荐
相关产品推荐

