You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现Dijkstra算法路径错误问题求助

C语言Dijkstra算法非法路径问题修复方案

核心问题定位

你遇到的非法路径问题,大概率是以下两个原因之一:

  • 邻接矩阵中非直接连通的节点权重未设为无穷大,导致算法误判存在直接路径
  • 前驱节点数组维护错误,路径回溯时跳过了必须的中间节点

针对性修复步骤

1. 修正邻接矩阵初始化逻辑

确保非直接连通的节点对权重设为INT_MAX(C语言中表示无穷大),自身到自身设为0,直接连通的节点设为对应权重。比如测试用例中C到F没有直接边,那么graph[C_idx][F_idx]必须是INT_MAX,不能是0或其他有效值。

2. 正确维护前驱节点数组

在更新节点最短距离时,必须同步更新该节点的前驱节点。比如当通过E节点更新F的最短距离时,F的前驱要设为E,而不是C。修正后的距离更新逻辑如下:

if (!visited[v] && graph[u][v] != INT_MAX && dist[v] > dist[u] + graph[u][v]) {
    dist[v] = dist[u] + graph[u][v];
    prev[v] = u; // 这里的u是当前找到的最短路径节点,确保前驱指向正确的中间节点
}

3. 修复路径回溯逻辑

从终点开始,沿着前驱节点依次回溯到起点,避免跳过任何节点。可以用数组存储回溯路径,再反向输出得到正确顺序:

// 回溯路径示例
char path[MAX_NODES][MAX_NAME_LEN];
int path_len = 0;
int curr = end_idx;
while (curr != -1) {
    strcpy(path[path_len], nodes[curr]);
    path_len++;
    if (curr == start_idx) break;
    curr = prev[curr];
}
// 反向输出路径
for (int i = path_len - 1; i >= 0; i--) {
    printf("%s", path[i]);
    if (i > 0) printf("->");
}

修正后的完整C代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#define MAX_NODES 10
#define MAX_NAME_LEN 10

// 查找节点对应的数组索引
int find_node_index(char nodes[][MAX_NAME_LEN], int num_nodes, char *name) {
    for (int i = 0; i < num_nodes; i++) {
        if (strcmp(nodes[i], name) == 0) {
            return i;
        }
    }
    return -1;
}

void dijkstra(int graph[MAX_NODES][MAX_NODES], int num_nodes, int start_idx, int end_idx, char nodes[][MAX_NAME_LEN]) {
    int dist[MAX_NODES];
    int visited[MAX_NODES];
    int prev[MAX_NODES];

    // 初始化:距离设为起点到各节点的直接距离,前驱默认指向起点(可达的话)
    for (int i = 0; i < num_nodes; i++) {
        dist[i] = graph[start_idx][i];
        visited[i] = 0;
        prev[i] = (graph[start_idx][i] != INT_MAX && i != start_idx) ? start_idx : -1;
    }
    dist[start_idx] = 0;
    visited[start_idx] = 1;

    // 迭代处理所有节点
    for (int i = 1; i < num_nodes; i++) {
        // 找到未访问的最短距离节点
        int min_dist = INT_MAX;
        int u = -1;
        for (int j = 0; j < num_nodes; j++) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                u = j;
            }
        }
        if (u == -1) break; // 无更多可达节点
        visited[u] = 1;

        // 更新邻接节点的距离和前驱
        for (int v = 0; v < num_nodes; v++) {
            if (!visited[v] && graph[u][v] != INT_MAX && dist[v] > dist[u] + graph[u][v]) {
                dist[v] = dist[u] + graph[u][v];
                prev[v] = u;
            }
        }
    }

    // 输出结果
    printf("最短路径:");
    if (dist[end_idx] == INT_MAX) {
        printf("无可达路径\n");
        return;
    }

    // 回溯路径并存储
    char path[MAX_NODES][MAX_NAME_LEN];
    int path_len = 0;
    int curr = end_idx;
    while (curr != -1) {
        strcpy(path[path_len], nodes[curr]);
        path_len++;
        if (curr == start_idx) break;
        curr = prev[curr];
    }

    // 反向输出得到正确路径顺序
    for (int i = path_len - 1; i >= 0; i--) {
        printf("%s", path[i]);
        if (i > 0) printf("->");
    }
    printf("\n最短距离:%d\n", dist[end_idx]);
}

int main() {
    int num_nodes;
    char nodes[MAX_NODES][MAX_NAME_LEN];
    int graph[MAX_NODES][MAX_NODES];
    char start_node[MAX_NAME_LEN], end_node[MAX_NAME_LEN];

    printf("输入节点数量:");
    scanf("%d", &num_nodes);
    getchar(); // 清除换行符

    printf("输入节点名称(每行一个):\n");
    for (int i = 0; i < num_nodes; i++) {
        fgets(nodes[i], MAX_NAME_LEN, stdin);
        nodes[i][strcspn(nodes[i], "\n")] = '\0'; // 去掉末尾换行
    }

    // 初始化邻接矩阵为无穷大
    for (int i = 0; i < num_nodes; i++) {
        for (int j = 0; j < num_nodes; j++) {
            graph[i][j] = INT_MAX;
        }
        graph[i][i] = 0; // 自身到自身距离为0
    }

    printf("输入邻接矩阵(每行%d个数字,无穷大输入-1):\n", num_nodes);
    for (int i = 0; i < num_nodes; i++) {
        for (int j = 0; j < num_nodes; j++) {
            int val;
            scanf("%d", &val);
            if (val != -1 && i != j) {
                graph[i][j] = val;
            }
        }
    }

    printf("输入起点和终点:");
    scanf("%s %s", start_node, end_node);

    int start_idx = find_node_index(nodes, num_nodes, start_node);
    int end_idx = find_node_index(nodes, num_nodes, end_node);

    if (start_idx == -1 || end_idx == -1) {
        printf("节点不存在\n");
        return 1;
    }

    dijkstra(graph, num_nodes, start_idx, end_idx, nodes);

    return 0;
}

测试用例验证

用你提到的测试场景输入:

节点数量:5
节点名称:
A
B
C
E
F
邻接矩阵:
0 -1 2 -1 -1
-1 0 -1 3 -1
-1 -1 0 1 -1
-1 -1 -1 0 1
-1 -1 -1 -1 0
起点:A,终点:F

运行后会输出正确路径:A->C->E->F,最短距离为4。

内容的提问来源于stack exchange,提问作者O Z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 10:57:49