单源最短路径的迪克斯特拉(Dijkstra)算法

Dijkstra算法

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点(节点需为源点)到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,注意该算法要求图中不存在负权边。

 实例:假设有A,B,C,D四个城市,(这里讨论的是有向网) 它们的距离为:  A->B(10),A->C(11),B->D(12),C->D(13);

所谓単源路径就是解决从源点 A开始找出到其他城市的最短距离(除本身外的其他所有城市)。Dijkstra算法可以求出A->B(10),A->C(11),A->D(22);

拓展2:多源最短路径(常用Floyd算法)是解决任意两点间的最短路径的一种算法,(不局限于从源点出发,到其他各个顶点 )可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd算法的时间复杂度为O(N3),空间复杂度为O(N2)。

代码

/*
  @ Dijkstra算法(単源最短路径)
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define MAXV 100
#define LIMITLESS 9999    //定义为无穷大,默认为节点间不存在联系
using namespace std;
typedef struct
{
   char info; //顶点其他信息
}VertexType;

typedef struct MGraph
{
    int v;     //顶点数
    int e;    //边数
    int edges[MAXV][MAXV];//邻接矩阵的数组表现
    VertexType vexs[MAXV]; //顶点信息
}MGraph;

void creat(MGraph *G)
{
    int i, j, k, w;
    int start, end;
    printf("请输入顶点数和边数:\n");
    scanf("%d%d", &(G->v), &(G->e));
    getchar();
    printf("请输入顶点信息:\n");
    for (i = 0; i<G->v; i++)
    {
        scanf("%c", &(G->vexs[i].info));
    }
    for (i = 0; i<G->v; i++)
    {
        for (j = 0; j<G->v; j++)
        {
            G->edges[i][j] = LIMITLESS;
        }
    }
    printf("输入图的顶点边的下标值和它的权值:\n");
    for (k = 0; k<G->e; k++)
    {
        scanf("%d%d%d", &start, &end, &w);
        G->edges[start][end] = w;
    }
}

void print(MGraph *G)
{
    int i, j;
    printf("顶点数:%d,边数:%d\n", G->v, G->e);
    printf("%d个顶点的信息:\n", G->v);
    for (i = 0; i<G->v; i++)
    {
        printf("%5c",G->vexs[i].info);
    }
    printf("\n各个顶点的连接情况:\n");
    printf("\t");
    for (i = 0; i<G->v; i++)
    {
        printf("[%d]\t", i);
    }
    printf("\n");
    for (i = 0; i<G->v; i++)
    {
        printf("[%d]\t", i);
        for (j = 0; j<G->v; j++)
        {
            if (G->edges[i][j] == LIMITLESS)
            {
                printf("oo\t");
            }
            else
            {
                printf("%d\t", G->edges[i][j]);
            }
        }
        printf("\n");
    }
}

void Ppath(MGraph *g,int path[], int i, int v) //前向递归查找路径上的顶点,但不包含起点与终点的路径值
{
    int k;
    k = path[i];
    if (k == v)   //无中间节点,退出
    {
        return;
    }
    Ppath(g,path, k, v);
    printf("%c",g->vexs[k]);
}

void Dispath(MGraph *g,int dist[], int path[], int s[], int n, int v)
{
    int i;
    for (i = 0; i < n; i++)
    {
        if (s[i] == 1)
        {
            printf("从%c到%c的最短路径长度为:%d\t路径为:", g->vexs[v], g->vexs[i], dist[i]);
            printf("%c",g->vexs[v]);     //输出路径上的起点
            Ppath(g,path, i, v);  //输出路径上的中间点
            printf("%c\n",g->vexs[i]); //输出路径上的终点
        }
        else
        {
            printf("从%c到%c不存在路径\n", g->vexs[v], g->vexs[i]);
        }
    }
}

void Dijkstra(MGraph *g, int v)
{
    int mindis, i, j, u;
    int s[MAXV];     //表示这个顶点是否存入最短路线中(0表示未加入,1表示已加入)
    int dist[MAXV]; //表示起始点到此顶点的距离
    int path[MAXV];//表示此点的上一步是哪一个顶点
    for (i = 0; i < g->v; i++)
    {
        s[i] = 0;
        dist[i] = g->edges[v][i];
        if (g->edges[v][i] < LIMITLESS)
        {
            path[i] = v;
        }
        else
        {
            path[i] = -1;
        }
    }
    s[v] = 1;
    path[v] = 0;
    for (i = 0; i < g->v; i++)
    {
        mindis = LIMITLESS;         //mindis置最小长度初值
        for (j = 0; j < g->v; j++) //选取不在s中且具有最小距离的顶点u
        {
            if (s[j] == 0 && dist[j] <mindis)
            {
                mindis = dist[j];
                u = j;
            }
        }
        s[u] = 1;
        for (j = 0; j < g->v; j++)
        {
            if (s[j] == 0)
            {
                if (g->edges[u][j] < LIMITLESS&&dist[u] + g->edges[u][j] < dist[j])
                {
                    dist[j] = dist[u] + g->edges[u][j];
                    path[j] = u;
                }
            }
        }
    }
    Dispath(g ,dist, path, s, g->v, v);
}

int main(void)
{
    MGraph *g;
    g = (MGraph *)malloc(sizeof(MGraph));
    creat(g);
    print(g);
    Dijkstra(g,0);
    return 0;
}
 

《单源最短路径的迪克斯特拉(Dijkstra)算法》

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/lfb637/article/details/78758080
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞