【每天一点算法】Dijkstra最短路径算法

我是在运筹学这门课里面接触到这个算法的,先是在书上大概理解了这种方法的人脑思维方式。但是我坚信,运用机器实现我们学到的每一个算法将会帮助我们更好地理解我们所处的信息化时代,下面就开始吧。

一、Dijkstra算法概述
Dijkstra算法是一个单向路径最短算法,也就是在一个图中不能存在负权边,该算法通过外散的形式逐步确定每一个节点到起始结点的最短路径。这种算法的具体解释在数据结构与算法、运筹学、图论等相关书籍中都有具体介绍,可以参阅相关书籍(Tips:找一些国内的比较老的书籍,或者是国外的书籍看)

二、程序实现思路

  • 使用二维数组存储一个邻接矩阵什么是邻接矩阵?可以Google一下),使用这个邻接矩阵来存储一个单源有向图 。
  • 为每一个节点准备三个属性,存储在三个数组中(这是程序实现的核心所在),这三个数组分别是flag,previous,distance,因此我也形象地把这种程序实现方法称为FPD法。
  • 一开始的时候,程序有一张图,图中的每个节点带着三个属性数据,我们进行路径搜索的第一步是确定起点,这一步会对着三个属性数据进行一次更新,后面再对这三个数据进行(N-1)次更新就完成了,这里的N是结点数目
  • 更新结束后,我们会得到两个很重要的数组previolus和distance,previous中保存的是每一个结点的前驱结点(也就是到这个结点的最短路径所经过的最后一个结点),通过previous,我们可以反向回溯得到最短路径,distance就是到每一个结点的最短路径了。

三、核心代码解析

void dijkstra(int start, int *previous, int *distance)
{
    int i, j, k ;
    int min, temp, flag[MAX];

    //一张图中,每个节点都有三个状态参数:是否找到最短路径flag,前驱结点previous,每个结点到前驱结点的距离distance


    //下面是初始化,一开始所有的结点都是没有得到最短路径,前驱结点是起始结点,每个结点到前驱结点的距离可以从邻接矩阵中获得
    for(i = 0; i < Node; i++){
            flag[i] = 0;
            previous[i] = 0;
            distance[i] = Matrix[start][i];
    }

    //对初始结点属性参数进行初始化
    flag[start] = 1;
    previous[i] = 0;
    distance[start] = 0;

    for(i = 1; i < Node; i++){
        min = INF;

        //找到各个结点中距离前驱结点最近的点以及相应的最短距离
        for(j = 0; j < Node; j++){
            if(flag[j] == 0 && distance[j] < min){
                min = distance[j];
                k = j;
            }
        }

        //标记结点k已经找到最短路径
        flag[k] = 1;

        //修正前驱结点,更新起始点到各点的最短距离
        for(j = 0; j < Node; j++){
            temp = (Matrix[k][j] == INF ? INF : (min + Matrix[k][j]));
            if(flag[j] == 0 && (temp < distance[j])){
                distance[j] = temp;
                previous[j] = k;
            }
        }
    }
    printf("%d", distance[6]);
}

1、当我们传入起始点后,算法首先会根据这个起始点来对所有结点的属性信息进行第一次更新,具体有哪些更新,代码中写得很清楚
2、下面继续进行N-1次更新,更新的思想是这样的:遍历所有结点,在还没有找到最短路径的结点中找到一个当前到路径最小的结点,并将这个结点号记住,然后利用这个结点号来对所有结点进行更新,具体的更新方式看代码最后一部分,然后继续循环,循环结束后,我们就可以得到我们需要的信息啦。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值