【无标题】

/***************************************

today we are talking about the Dijkstra algorithm

time:2023.11.6

producer:Jiang Yizhou

使用此程序需输入以下内容创建图G:
第一步:7 12
第二步:0123456
第三步:依次输入下面的内容,输入完一行就按下换行键
0 1 6
0 2 3
1 2 2
1 3 1
1 4 4
2 3 5
2 5 7
3 4 3
3 5 6
4 5 2
4 6 2
5 6 3

*****************************************/


#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS  1
#pragma warning(disable:6031)
#pragma warning(disable:4996)
#define MaxVerterNum 100        // 顶点数目的最大值
#define INFINITY 65535            // 用65535代表 ∞

typedef char VertexType;        // 顶点的数据类型
typedef int EdgeType;            // 带权图中边上权值的数据类型

/* 邻接矩阵的存储结构 */
typedef struct
{
    VertexType Vexs[MaxVerterNum];                    // 顶点表
    EdgeType Edge[MaxVerterNum][MaxVerterNum];        // 邻接矩阵
    int vexNum, arcNum;                                // 图当前顶点数和弧数
}MGraph;

/*清除缓冲区的换行符*/
void Clean(void)
{
    while (getchar() != '\n')
        continue;
}

/* 建立无向网图的邻接矩阵表示 */
void CreateMGraph(MGraph* G);

/* 迪杰斯特拉(Dijkstra) 算法*/
typedef int Patharc[MaxVerterNum];            // 用于存储最短路径下标的数组,从源点Vi到顶点Vj之间的最短路径的前驱
typedef int ShortPathTable[MaxVerterNum];    // 用于存储到各点最短路径的权值和
void ShortestPath_Dijkstra(MGraph G, int v0, Patharc path, ShortPathTable D);

/* 输出最短路径 */
/* Dijkstra算法的结果输出 */
void Show_ShortestPath_Dijkstra(Patharc path, ShortPathTable dist, MGraph G, int v0);

int main(void)
{
    MGraph G;
    Patharc path;
    ShortPathTable dist;
    CreateMGraph(&G);
    for (int i = 0; i < G.vexNum; i++) // 输出各点到各点的最短路径序列,不再局限于一个顶点
    {
        ShortestPath_Dijkstra(G, i, path, dist);
        Show_ShortestPath_Dijkstra(path, dist, G, i);
    }
    return 0;
}

/* 建立无向网图的邻接矩阵表示 */
void CreateMGraph(MGraph* G)
{
    int i, j, k, w;
    printf("请输入顶点数和边数:");
    scanf("%d %d", &G->vexNum, &G->arcNum);            // 获取无向图顶点数和边数
    printf("请输入全部顶点信息:\n");
    Clean();                                        // 将换行符去除
    for (i = 0; i < G->vexNum; i++)                    // 读取顶点信息,建立顶点表
        scanf("%c", &G->Vexs[i]);
    for (i = 0; i < G->vexNum; i++)
        for (j = 0; j < G->vexNum; j++)
            G->Edge[i][j] = INFINITY;                // 邻接矩阵初始化
    for (k = 0; k < G->arcNum; k++)                    // 读入arcNum条边,建立邻接矩阵
    {
        printf("请输入边(Vi, Vj)上的下标i,下标j和权w:\n");
        scanf("%d %d %d", &i, &j, &w);                // 获取边和权
        G->Edge[i][j] = w;                            // 无向图矩阵对称
        G->Edge[j][i] = G->Edge[i][j];
    }
    return;
}

/* 迪杰斯特拉(Dijkstra) 算法*/
void ShortestPath_Dijkstra(MGraph G, int v0, Patharc path, ShortPathTable dist)
{
    int v, w, k, min;
    int final[MaxVerterNum];                /* final[w] = 1表示求得顶点 v0 至 vw的最短路                    径,即已访问过顶点vw*/
    for (v = 0; v < G.vexNum; v++)
    {
        final[v] = 0;                        // 全部顶点初始化为未知最短路径状态
        dist[v] = G.Edge[v0][v];            // 将与v0点有连线的顶点加上权值
        path[v] = -1;                        // 初始化路劲数组p为-1
    }
    dist[v0] = 0;                            // v0至v0路径为0
    final[v0] = 1;                            // v0至v0不需要路径
    /* 开始主循环,每次求得v0到某个顶点v的最短路径*/
    for (v = 1; v < G.vexNum; v++)
    {
        min = INFINITY;                        // 当前所知离v0顶点的最近距离
        for (w = 0; w < G.vexNum; w++)        // 寻找离v0最近的顶点
        {
            if (!final[w] && dist[w] < min)
            {
                k = w;
                min = dist[w];                // w顶点离v0顶点更近
            }
        }
        final[k] = 1;                        // 将目前找到的最近的顶点置为1
        for (w = 0; w < G.vexNum; w++)        // 修正当前最短路径及距离
        {
            /* 如果经过v顶点的路径比现在这条路径的长度短的话 */
            if (!final[w] && (min + G.Edge[k][w] < dist[w]))
            {
                /* 找到了更短的路径,修改D[w]和P[w] */
                dist[w] = min + G.Edge[k][w];    // 修改当前路径长度
                path[w] = k;
            }
        }
    }
}

/* 输出最短路径 */
/* Dijkstra算法的结果输出 */
void Show_ShortestPath_Dijkstra(Patharc path, ShortPathTable dist, MGraph G, int v)
{
    int w, k;
    printf("V%d到各点的最短路径如下:\n", v);
    for (w = 0; w < G.vexNum; w++)
    {
        if (w != v)
        {
            printf("V%d-V%d weight: %d", v, w, dist[w]);
            k = path[w];
            printf(" path: V%d", w);
            while (k != -1)  // 当 k = -1 ,结束循环并输出源点
            {
                printf(" <- V%d", k);
                k = path[k];
            }
            printf(" <- V%d\n", v);
        }
    }
    printf("\n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值