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

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

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

我们可以通过画一张表,写每一个步骤来帮助自己理解:
三十天挑战数据结构(11)图的最短路径之Dijkstra算法
下面放代码:

#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");
}

程序运行结果:
三十天挑战数据结构(11)图的最短路径之Dijkstra算法
所以这个图从v0到v8的最短路径走法是:
v0 -> v1 -> v2 -> v4 -> v3 -> v6 -> v7 -> v8
距离是16,可以通过相加算出,程序里面就没有单独print出来了。

上一篇:【算法】Dijkstra算法求最短路径


下一篇:dijkstra和dijkstra堆优化模板