最短路径--Floyd、Dijkstra、Bellman、SPFA算法
前言
最短路径是数据结构-图中的一个经典问题,求解最短路径的问题,有四种算法,这四种算法各有各的不同,分别是:
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算法相关推荐
- 7-9 旅游规划 (25分) 【最短路径 Floyd+Dijkstra】
有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便 ...
- 最短路径-Floyd(佛洛伊德算法)
佛洛伊德算法时间复杂度为O(n^3),其中n为顶点的个数. Floyd可求出任何一对顶点之间的最短路径.允许图中有带负权值的边,但是不允许有包含带负权值的边组成的回路. #include <io ...
- 【最短路径问题笔记】SPFA算法及负环的判断
dis数组:记录源点到每个结点最短路径值 in数组:记录结点进队次数 vis数组:记录结点是否在队列中 设立队列用来保存待优化的结点: 优化时每次取出队首结点cur,并且用cur点当前的最短路径对u点 ...
- (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法
一.floyd 1.介绍 floyd算法只有五行代码,代码简单,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3),可以求多源最短路问题. 2.思想: Floyd算法的基本思想如下:从任意 ...
- 最短路径(Dijkstra、Bellman-Ford和SPFA算法)
最短路径(Dijkstra.Bellman-Ford和SPFA算法) 前言 图的存储方式 邻接矩阵 邻接表 链表建立 利用vector 结构体 核心思路 Dijkstra算法 图解 基本思想 求解步骤 ...
- 最短路径——Floyd算法HDU Today(hdu2112)
最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 算法具体的形式包括: 确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题. 确定终点的 ...
- Bellman-ford和SPFA算法
目录 一.前言 二.Bellman-ford算法 1.算法思想 2.算法复杂度 3.判断负圈 4.出差(2022第十三届国赛,lanqiaoOJ题号2194) 三.SPFA算法:改进的Bellman- ...
- 【转载】SPFA算法
算法简介 SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算.也有人说SPFA本来就是Bellman-Ford ...
- 四大算法解决最短路径问题(Dijkstra+Bellman-ford+SPFA+Floyd)
什么是最短路径问题? 简单来讲,就是用于计算一个节点到其他所有节点的最短路径. 单源最短路算法:已知起点,求到达其他点的最短路径. 常用算法:Dijkstra算法.Bellman-ford算法.SPF ...
最新文章
- Java多线程的几种实现方法
- HTML5本地存储localstorage
- 使用Android SDK Manager下载sdk时总是出现中断异常的解决办法。
- php如何将mysql数据库中的admin字段赋值给session_php实现将Session写入数据库
- Problem E: 高于均分的学生
- LeetCode:Balanced Binary Tree
- JVM原理-jvm内存模型
- jQuery支持移动触摸设备的Lightbox插件
- 区块链:5、匿名性和隐私性
- python-网络编程-tcp/ip认识(一)
- python装饰器讲解_Python装饰器讲解的不能再通俗易懂了(建议收藏)
- vgc机器人编程1到13题_工业机器人编程与实操 期末试题
- 工作簿中工作表内容批量提取
- 机器人动作编辑器说明
- 彻底搞清类的依赖关系、关联关系、聚合关系、组合关系
- HTML5 2D平台游戏开发#9蓄力技
- 1.3-聊天机器人的模块和框架
- HTTP 与 HTTPS 的理解
- 计算机主板 大 小,电脑主板选大的还是小的比较好?
- python:实现数组去重算法(附完整源码)