基于邻接矩阵的Dijkstra算法

通过Dijkstra算法,求两点间最短路径及长度。

输入样例说明:
3 3//第一组输入的顶点数和边数
A B C//三个顶点
A B 1//从A到B有权值为1的边,以此类推
B C 1
A C 3
A C//求A到C的最短路径
···//其余输入
0 0//输入结束

输入样例:
3 3
A B C
A B 1
B C 1
A C 3
A C
6 8
A B C D E F
A F 100
A E 30
A C 10
B C 5
C D 50
E D 20
E F 60
D F 10
A F
5 6
A B C D E
A B 5
A E 50
B E 10
A D 10
D C 10
E C 10
A C
0 0

输出样例:
2
A B C
60
A E D F
20
A D C

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

#define MaxVertexNum 10
#define MaxInt 999

typedef struct MGraph{
    
    
    char vex[MaxVertexNum];
    int edge[MaxVertexNum][MaxVertexNum];
    int vexNum, edgeNum;
} MGraph;/*ˈmeɪtrɪks*/

void GraphInit(MGraph *G);
void GraphShow(MGraph G);
void addEdge(MGraph *G, char src, char des, int weight);
int Dijkstra(MGraph G, int srcPos, int desPos, char *path);

int main() {
    
    
    MGraph G;

    while (scanf("%d %d%*c", &G.vexNum, &G.edgeNum) && G.vexNum != 0) {
    
    
        char src, des;//源点和目标点
        int srcPos, desPos;//源点和目标点的位序
        int weight;//边的权值
        char path[MaxVertexNum] = "";//最短路径

        /*构造无向图*/
        GraphInit(&G);
        for (int i = 0; i < G.vexNum; i++) scanf("%c%*c", G.vex + i);
        for (int i = 0; i < G.edgeNum; i++) {
    
    
            scanf("%c %c %d%*c", &src, &des, &weight);
            addEdge(&G, src, des, weight);
        }

        /*Dijkstra求最短路径*/
        scanf("%c %c%*c", &src, &des);
        for (int i = 0; i < G.vexNum; i++) {
    
    
            /*将源目结点转化为对应位序*/
            if (G.vex[i] == src) srcPos = i;
            if (G.vex[i] == des) desPos = i;
        }
        printf("%d\n", Dijkstra(G, srcPos, desPos, path));
        for (int i = strlen(path) - 1; i >= 0; i--) {
    
    
            printf("%c%c", path[i], !i ? 10 : 32);//反向输出
        }
    }

    return 0;
}

int Dijkstra(MGraph G, int srcPos, int desPos, char *path) {
    
    
    int dist[MaxVertexNum];//每个结点与源点的最短路径长度,记为dist
    int final[MaxVertexNum];//标记每个结点是否已经访问,已访问的结点记为集合S
    int lastAlter[MaxVertexNum];//最后一次修改当前结点dist值的结点的下标,用于回溯路径

    /*初始化*/
    for (int i = 0; i < G.vexNum; i++) {
    
    
        lastAlter[i] = srcPos;//从目标结点回溯到源点的路径恰好为path,所以回溯结束的标志就是访问到了源点
        dist[i] = G.edge[srcPos][i];//初始值就是源点到各个结点的弧的长度
        final[i] = 0;//初始时每个结点都没访问
    }
    final[srcPos] = 1;//源点默认已经被访问

    /*主循环*/
    for (int i = 0; i < G.vexNum; i++) {
    
    
        int minDis = MaxInt;//最短路径长度
        int minPos = -1;//最短路径对应结点

        /*选出一个不在集合S中且距离源点最近的结点*/
        for (int j = 0; j < G.vexNum; j++) {
    
    
            if (!final[j]) {
    
    
                if (dist[j] < minDis) {
    
    
                    /*更新最短路径长度和对应结点*/
                    minDis = dist[j];
                    minPos = j;
                }
            }
        }

        final[minPos] = 1;//将当前最短路径对应的结点加入集合S
        if (minPos == desPos) break;//已经把目标结点加入了集合S

        /*更新最短路径和距离*/
        for (int j = 0; j < G.vexNum; j++) {
    
    
            //如果当前结点不在S中,且加入了新结点后当前结点与源点的距离减小,更新距离
            if (!final[j] && minDis + G.edge[minPos][j] < dist[j]) {
    
    
                dist[j] = minDis + G.edge[minPos][j];//更新距离
                lastAlter[j] = minPos;//G.vex[minPos]结点修改了G.vex[j]结点的dist值
            }
        }
    }

    /*通过lastAlter回溯得到路径path*/
    int node = desPos, i = 0;
    while (node != srcPos) {
    
    
        path[i++] = G.vex[node];
        node = lastAlter[node];
    }
    path[i] = G.vex[srcPos];

    return dist[desPos];
}

void GraphInit(MGraph *G) {
    
    
    for (int i = 0; i < G->vexNum; i++) {
    
    
        for (int j = 0; j < G->vexNum; j++) {
    
    
            G->edge[i][j] = MaxInt;
        }
    }
}

void GraphShow(MGraph G) {
    
    
    printf("  ");
    for (int i = 0; i < G.vexNum; i++) {
    
    
        printf("%3c%c", G.vex[i], i == G.vexNum - 1 ? 10 : 32);
    }
    for (int i = 0; i < G.vexNum; i++) {
    
    
        printf("%c ", G.vex[i]);
        for (int j = 0; j < G.vexNum; j++) {
    
    
            if (G.edge[i][j] == MaxInt) {
    
    
                printf("%3c%c", 'x', j == G.vexNum - 1 ? 10 : 32);
            } else {
    
    
                printf("%3d%c", G.edge[i][j], j == G.vexNum - 1 ? 10 : 32);
            }
        }
    }
}

void addEdge(MGraph *G, char src, char des, int weight) {
    
    
    int i = 0, j = 0;

    while (G->vex[i] != src) i++;
    while (G->vex[j] != des) j++;
    G->edge[i][j] = G->edge[j][i] = weight;
}

猜你喜欢

转载自blog.csdn.net/qq_43686863/article/details/123623493