算法学习:Dijkstra入门

前言:

        最近在刷算法模板题的时候发现最短路卡掉了我很多脑细胞,所以特别冲浪了一下学习最短路算法这个好理解的算法。

算法简介:

        Dijkstra就是个求单源最短路的算法,单源最短路,就是从一个起点出发到其他所有点的最短路。(与之相对的多源最短路,即能求任意两点之间的最短路)Dijkstra算法使用的思想是贪心,要知道贪心是最符合人类思维的算法,时间复杂度是O(N^2)的,使用堆优化的复杂度是O((N+M)*logN)的,非常高效。

        Dijkstra的贪心思路是这样的:

        为了方便起见,我们定义 点集S为已经确定最短路的点的集合,下图用红色点表示;点集U为更新过的,但是没有确定为最短路的点的集合,下图用蓝色点表示;点集V为还没有更新过的点的集合,下图用白色点表示。

        1.从起点出发,扩展并更新它能连接的所有点的数值。以下图为样例,假设从1点出发。那么下图的模拟就是,先从1点出发,并且确定1是最短路的点,那么它就是已经确定最短路的点(因为自己到自己的最短路是0,什么?你问后面连接负数边权?废话,Dijkstra本来就不能处理负边权)。向外直接连接的点是2、3、4、7,经过1过程那么扩展成蓝色点。

         2.从蓝点里找一个数值最小的点,以它为中继点执行像1.一样的操作,就是从上图的2点(数值是2)出发继续扩展,同时需要注意的是,2点这个时候可以确定是了它的数值就是到起点的最短路了,证明见后。模拟上图就成为了下图。因为2点直接连接的是1点和6点,而1点已经红了,那么只能更新没更新过的6点的数值,让6点蓝起来。

        3.重复2.的步骤,找到蓝点里面数据最小的那个用它来遍历下一步。(上图为3点扩展,成为下图),由3点扩展5点,把3点变红,5点变蓝。

 

                4.重复步骤,蓝点最小的是5点,从5点扩展,5点直接连接到1、4、7。1点红了在1.解释过,不在扩展。重点来了!4、7点都是蓝点怎么办。别急,5点连接到4、7,那么就意味着,1点到4和7的最短路可能会被更新(至于为什么证明在后面),那么从5点的数据到4点的数据更新吗?5->4边权是4,5数据是7。7+4=11 > 4点数据“7”,所以没必要更新。因为1->4的路径比1->3->5->4更好。同理5->7也是一样不需要更新。这个时候让5点红了就行。

         5.继续扩展7点,无法更新6点.......继续更新4点,突然发现 7+1=8 < 10,所以更新6点

        6.        6点无法更新,直接变红,算法over。就是说,从1到2..7的最短路分别是2、4、7、7、8、5。

我觉得我讲的挺详细的,如果还不明白,可以不用学了私信我。

        至于这种算法为什么正确,且看下列证明。

        开始的时候默认是起始点位于S点集 中,

        从起始点扩展的点都加入U点集 中,那么显然可以看出U中连到S中,U中最小的那个连到S中的话,一定意味着这个点能到达起点是最短路。

        

 证毕

下面给出伪代码:(连接矩阵存图)

w[i][j];//从点i到点j的边权 
    map[V];//第一个点到其他点的边权记录 
    memset(map,0x3f);//初始化任意两个点都最大 
    map[1]=0;//第一个点到自身的最短路一定是为0
    for(int i=1;i<=n;i++){
        int t=-1; // 在还未确定最短路的点中,寻找距离最小的点
        for(int j=1;j<=n;j++)//从一号点开始
            if(!vis[j] and (t==-1 or map[t]>map[j]))
            t=j;
        vis[t]=1;
        // 用t更新其他点的距离
        for(int j=1;j<=n;j++)
            map[j]=min(map[j],map[t]+w[t][j]);
    }
    if(map[n]==INF) return -1;//如果第n个点路径为无穷大即不存在最低路径
    map[n] out!!;

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值