前言

  最短路径是数据结构-图中的一个经典问题,求解最短路径的问题,有四种算法,这四种算法各有各的不同,分别是:

  Floyd算法、Dijkstra算法、Bellman算法以及SPFA算法。

  最常用的是前两者,当然你也可以都掌握,毕竟各有各的好处。

1.Floyd-Warshall算法

  优点:实现代码极其简便,比较好理解。

  缺点:时间复杂度较高,为O(n3),适用于数据复杂度不高的题目

  此方法适用于解决多源图的最短路问题,用枚举的方式,遍历比较哪种路径最短。

  代码实现如下:

//floyd-warshall算法

for(int k=1; k<=n; k++)
{for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){if(map[i][j]>map[i][k]+map[k][j]){map[i][j]=map[i][k]+map[k][j];}}}
}

2.Dijkstra算法

  注意:这个算法只适用于无负权值的单元最短路问题,这种算法用到了贪心,和最小生成树的Prim算法有点类似

  思路:对每个找到的点进行标记,每标记一个点,就进行一次数据的更新,遍历完所有的点,确定最后的路径即为最短路径,就结束。

  时间复杂度:O(n2)  可进行优化,堆/优先队列优化后的时间复杂度:O(nlogn)

  代码实现如下:

//Dijkstra算法#define inf 0x3f3f3f3ffor(i=1; i<n; i++)
{min=inf;for(j=1; j<=n; j++)   //求出当前dis数组中离第一个顶点最短的距离的顶点的下标
    {if(book[j]==0 && dis[j]<min){min=dis[j];u=j;//记下这个点的下标
        }}book[u]=1;for(k=1; k<=n; k++){if(a[u][k]<inf){if(dis[k]>dis[u]+a[u][k])//若找到其他途径比从1号顶点直接到目的顶点的距离短,则替换掉
            {dis[k]=dis[u]+a[u][k];}}}}

3.Bellman-Ford算法 O(NE)

  此方法适用于单源最短路径。

  优点:可以求出存在负边权情况下的最短路径。

  缺点:无法解决存在负权回路的情况。

  时间复杂度:O(NE),N是顶点数,E是边数。

  算法思想:很简单。一开始认为起点是“标记点”(dis[1] = 0),每一次都枚举所有的边,必然会有一些边,连接着“未标记的点”和“已标记的点”。

       因此每次都能用所有的“已标记的点”去修改所有的“未标记的点”,每次循环也必然会有至少一个“未标记的点”变为“已标记的点”。

  代码实现如下:

//Bellman-Ford算法
for(int i = 1; i <= n - 1; i++)
{for(int j = 1; j <= E; j++)  //注意要枚举所有边,不能枚举点
   {if(dis[u] + w[j] < dis[v])  //u, v分别是这条边连接的两个点
      {dis[v] = dis[u] + w[j]pre[v] = u;}}
}

4.SPFA算法 O(KE)

  适用于:稀疏图(侧重于对边的处理)。

  时间复杂度:O(KE),K是常数,平均值为二,E是边数。

  背景:SPFA是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。

     这个算法简单地说就是队列优化的Bellman-Ford,利用了每个点不会更新次数太多的特点发明的此算法。

     SPFA在形式上和广度优先搜索非常类似,不同的是广度优先搜索中的一个点出了队列就不可能重新进入队列,

     但是SPFA中的一个点可能在出队列之后再次被放入队列,也就是说一个点修改过其他的点之后,过了一段时间可能会获得更短的路径,

     于是再次用来修改其他的点,这样反复进行下去。

  优化方法:
    1.循环队列(可以降低队列大小)
    2.SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j) < dist(i),则将j插入队首,否则插入队尾。

//SLF优化
if(!vis[temp])
{if(dis[q[head + 1]] < dis[temp])  //注意小于号不要写反,否则时间会爆
      {tail = (++tail - 1) % qxun + 1;q[tail] = temp;}else{q[head] = temp;if(--head == 0) head = qxun;}vis[temp] = 1;
}

    3.LLL:Large Label Last 策略,设队首元素为i,每次弹出时进行判断,队列中所有dist值的平均值为x,

       若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。

  代码实现如下:

//SPFA算法
#define inf 0x3f3f3f3fint spfa(int s,int n)
{queue<int>q;memset(dis,inf,sizeof(dis));dis[s]=0;memset(vis,0,sizeof(vis));memset(c,0,sizeof(c));q.push(s);vis[s]=1;flag=0;while(!q.empty()){int x;x=q.front();q.pop();vis[x]=0;//队头元素出队,并且消除标记for(int k=first[x]; k!=0; k=next[k]) //遍历顶点x的邻接表
        {int y=v[k];if(dis[x]+w[k]<dis[y]){dis[y]=dis[x]+w[k];  //松弛if(!vis[y])  //顶点y不在队内
                {vis[y]=1;    //标记c[y]++;      //统计次数q.push(y);   //入队if(c[y]>n)  //超过入队次数上限,说明有负环return flag=0;}}}}
}

参考资料:

   1.https://blog.csdn.net/zezzezzez/article/details/70245548

   2.https://blog.csdn.net/mashiro_ylb/article/details/78289790

   3.https://blog.csdn.net/tianhaobing/article/details/65443049

转载于:https://www.cnblogs.com/jkxsz2333/p/9520409.html

最短路径--Floyd、Dijkstra、Bellman、SPFA算法相关推荐

  1. 7-9 旅游规划 (25分) 【最短路径 Floyd+Dijkstra】

    有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便 ...

  2. 最短路径-Floyd(佛洛伊德算法)

    佛洛伊德算法时间复杂度为O(n^3),其中n为顶点的个数. Floyd可求出任何一对顶点之间的最短路径.允许图中有带负权值的边,但是不允许有包含带负权值的边组成的回路. #include <io ...

  3. 【最短路径问题笔记】SPFA算法及负环的判断

    dis数组:记录源点到每个结点最短路径值 in数组:记录结点进队次数 vis数组:记录结点是否在队列中 设立队列用来保存待优化的结点: 优化时每次取出队首结点cur,并且用cur点当前的最短路径对u点 ...

  4. (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法

    一.floyd 1.介绍 floyd算法只有五行代码,代码简单,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3),可以求多源最短路问题. 2.思想: Floyd算法的基本思想如下:从任意 ...

  5. 最短路径(Dijkstra、Bellman-Ford和SPFA算法)

    最短路径(Dijkstra.Bellman-Ford和SPFA算法) 前言 图的存储方式 邻接矩阵 邻接表 链表建立 利用vector 结构体 核心思路 Dijkstra算法 图解 基本思想 求解步骤 ...

  6. 最短路径——Floyd算法HDU Today(hdu2112)

    最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 算法具体的形式包括: 确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题. 确定终点的 ...

  7. Bellman-ford和SPFA算法

    目录 一.前言 二.Bellman-ford算法 1.算法思想 2.算法复杂度 3.判断负圈 4.出差(2022第十三届国赛,lanqiaoOJ题号2194) 三.SPFA算法:改进的Bellman- ...

  8. 【转载】SPFA算法

    算法简介 SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算.也有人说SPFA本来就是Bellman-Ford ...

  9. 四大算法解决最短路径问题(Dijkstra+Bellman-ford+SPFA+Floyd)

    什么是最短路径问题? 简单来讲,就是用于计算一个节点到其他所有节点的最短路径. 单源最短路算法:已知起点,求到达其他点的最短路径. 常用算法:Dijkstra算法.Bellman-ford算法.SPF ...

最新文章

  1. Java多线程的几种实现方法
  2. HTML5本地存储localstorage
  3. 使用Android SDK Manager下载sdk时总是出现中断异常的解决办法。
  4. php如何将mysql数据库中的admin字段赋值给session_php实现将Session写入数据库
  5. Problem E: 高于均分的学生
  6. LeetCode:Balanced Binary Tree
  7. JVM原理-jvm内存模型
  8. jQuery支持移动触摸设备的Lightbox插件
  9. 区块链:5、匿名性和隐私性
  10. python-网络编程-tcp/ip认识(一)
  11. python装饰器讲解_Python装饰器讲解的不能再通俗易懂了(建议收藏)
  12. vgc机器人编程1到13题_工业机器人编程与实操 期末试题
  13. 工作簿中工作表内容批量提取
  14. 机器人动作编辑器说明
  15. 彻底搞清类的依赖关系、关联关系、聚合关系、组合关系
  16. HTML5 2D平台游戏开发#9蓄力技
  17. 1.3-聊天机器人的模块和框架
  18. HTTP 与 HTTPS 的理解
  19. 计算机主板 大 小,电脑主板选大的还是小的比较好?
  20. python:实现数组去重算法(附完整源码)

热门文章

  1. WordPress 五个最好的免费幻灯片插件slideshow plugins
  2. 百度2009年度搜索风云榜发布
  3. Algorand算法实现(一)
  4. 控制算法(一)—— PID控制算法
  5. 基于可解释多模态深度学习的泛癌症整合组织-基因组分析
  6. opencv笔记(三十三)——Video Capture使用示例。读取视频
  7. decimal与BigDecimal用法
  8. C#——invoke和begininvoke 区别
  9. 涉及gcc wrap的一个问题的探索
  10. 名帖36 邓石如 隶书《作太元传》