三十天挑战数据结构(11)图的最短路径之Dijkstra算法

猝不及防地进入了“图”专题…
关于图的集中储存方法后面来补吧,先把关键算法一个Dijkstra算法一个Floyd算法给写了!

首先我们还是和之前一样,给出一个图并且确定它的存储结构:
在这里插入图片描述
最初学这个算法是在离散数学里面,当时也是急于复习,考前看了几遍勉强会算了,考完就忘差不多了。现在数据结构又遇到了它,会多一些印象,但还是重新学起为好。
Dijkstra算法的核心思想就是分步去对每个顶点求到达它的每一步的最小路径。举个最简单的栗子,要求上图中v0到v3的最短路径,我们可以通过v0到v1和v0到v4的最短路径加上v1-v3和v4-v3…整体思想是一种逐步地求。

我们可以通过画一张表,写每一个步骤来帮助自己理解:
在这里插入图片描述
下面放代码:

#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 9
#define INFINITE 65535

typedef int Patharc[MAXVEX];//存储最短路径下标
typedef int ShortPathTable[MAXVEX];//存储到各点最短路径的权值和
typedef char VertexType;
typedef int EdgeType;

typedef struct
{
    EdgeType arc[MAXVEX][MAXVEX];
    VertexType vexs[MAXVEX];
    int numVertexes, numEdges; //顶点个数,边数目
} MGraph;

//初始化邻接矩阵
void InitialGraph(MGraph *G)
{
    int i, j;
    for (i = 0; i < MAXVEX; i++)
    {
        for (j = 0; j < MAXVEX; j++)
        {
            if (i != j) //初始化时,给所有边赋成极大值
            {
                G->arc[i][j] = INFINITE;
            }
            else //i和j相等时对应权值为0
            {
                G->arc[i][j] = 0;
            }
        }
    }
}

//建立邻接矩阵储存图结构
void CreateGraph(MGraph *G)
{
    int i = 0;
    int x, y, data = 0;
    char c;
    printf("请输入顶点数目:");
    scanf("%d", &G->numVertexes);
    printf("请输入边的数目:");
    scanf("%d", &G->numEdges);
    printf("请依次输入顶点名称:\n");
    getchar();
    while ((c = getchar()) != '\n')
    {
        if (c == ' ')
            continue;
        else
        {
            G->vexs[i] = c;
            i++;
        }
    }
    printf("请依次输入两个顶点下标和之间的权值:\n");
    for (i = 0; i < G->numEdges; i++)
    {
        scanf("%d,%d %d", &x, &y, &data);
        G->arc[x][y] = data;
        G->arc[y][x] = data;
    }
    printf("图建立完毕...\n");
}

//核心算法
//P[v]为前驱顶点的下标,D[v]为v0到v的最短路径长度和
void ShortestPath_Dijkstra(MGraph *G, int v0, Patharc *P, ShortPathTable *D)
{
    int w, v, k, min;
    int final[MAXVEX];//记录是否求得最短路径
    for (v = 0; v < G->numVertexes; v++)
    {
        final[v] = 0;
        (*D)[v] = G->arc[v0][v];//记录v0点相邻的所有边权值
        (*P)[v] = 0;
    }
    (*D)[v0] = 0;
    final[v0] = 1;//初始化

    for (v = 1; v < G->numVertexes; v++)
    {
        min = INFINITE;
        for (w = 0; w < G->numVertexes; w++)
        {
            if(final[w] == 0 && (*D)[w] < min)
            {
                k = w;
                min = (*D)[w];
            }
        }
        final[k] = 1;//标记已找到最短路径
        for (w = 0; w < G->numVertexes; w++)
        {
            if(final[w] == 0 && (min + G->arc[k][w] < (*D)[w]))
            {
                (*D)[w] = min + G->arc[k][w];
                (*P)[w] = k;
            }
        }
    }
}

int main()
{
    int i, j=8;
    MGraph G;
    Patharc P;
    ShortPathTable D;
    InitialGraph(&G);
    CreateGraph(&G);
    ShortestPath_Dijkstra(&G, 0, &P, &D);
    printf("P数组为:"); 
    for (i = 0; i < MAXVEX; i++)
        printf("%d ", P[i]);
    printf("\n");
    printf("最短路径(逆向):8->");
    while(P[j] != 0)
    {
    	printf("%d->", P[j]);
    	j = P[j];
	}
	printf("0");
}

程序运行结果:
在这里插入图片描述
所以这个图从v0到v8的最短路径走法是:
v0 -> v1 -> v2 -> v4 -> v3 -> v6 -> v7 -> v8
距离是16,可以通过相加算出,程序里面就没有单独print出来了。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值