算法-贝尔曼-福特算法

注:该文是本博主记录学习之用,没有太多详细的讲解,敬请谅解!

一、简介

贝尔曼-福特算法(Bellman–Ford algorithm )用于计算出起点到各个节点的最短距离,支持存在负权重的情况
  • 它的原理是对图进行最多V-1次松弛操作,得到所有可能的最短路径。其优于狄克斯特拉算法的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达O(VE)。但算法可以进行若干种优化,提高了效率。

  • 贝尔曼-福特算法每次对所有的边进行松弛,每次松弛都会得到一条最短路径,所以总共需要要做的松弛操作是V - 1次。在完成这么多次松弛后如果还是可以松弛的话,那么就意味着,其中包含负环。

二、场景

  • 从起点出发是否存在到达各个节点的路径。
  • 从起点出发到达各个节点最短路径。
  • 是否存在负环路。

三、实现思路

  • 初始化时将起点s到各个顶点v的距离dist(s->v)赋值为∞,dist(s->s)赋值为0

  • 后续进行最多n-1次遍历操作,对所有的边进行松弛操作,假设:

    所谓的松弛,以边ab为例,若dist(a)代表起点s到达a点所需要花费的总数,
    dist(b)代表起点s到达b点所需要花费的总数,weight(ab)代表边ab的权重, 若存在:

    (dist(a) +weight(ab)) < dist(b)

    则说明存在到b的更短的路径,s->…->a->b,更新b点的总花费为(dist(a) +weight(ab)),父节点为a

  • 遍历都结束后,若再进行一次遍历,还能得到s到某些节点更短的路径的话,则说明存在负环路

四、java实现

如下图,求出A到各节点的最短路径

public class BellmanFord {/*** 实现思路:* 1、初始化时将起点起点到各个顶点的距离赋值为(无穷大)∞,当前起点距离赋值为0* 2、后续进行最多n-1次遍历操作* @param args*/public static void main(String[] args){//创建图Edge ab = new Edge("A", "B", -1);Edge ac = new Edge("A", "C", 4);Edge bc = new Edge("B", "C", 3);Edge be = new Edge("B", "E", 2);Edge ed = new Edge("E", "D", -3);Edge dc = new Edge("D", "C", 5);Edge bd = new Edge("B", "D", 2);Edge db = new Edge("D", "B", 1);//需要按图中的步骤步数顺序建立数组,否则就是另外一幅图了,//从起点A出发,步骤少的排前面Edge[] edges = new Edge[] {ab,ac,bc,be,bd,ed,dc,db};//存放到各个节点所需要消耗的时间HashMap<String,Integer> costMap = new HashMap<String,Integer>();//到各个节点对应的父节点HashMap<String,String> parentMap = new HashMap<String,String>();//初始化各个节点所消费的,当然也可以再遍历的时候判断下是否为Null//i=0的时候costMap.put("A", 0); //源点costMap.put("B", Integer.MAX_VALUE);costMap.put("C", Integer.MAX_VALUE);costMap.put("D", Integer.MAX_VALUE);costMap.put("E", Integer.MAX_VALUE);//进行节点数n-1次循环for(int i =1; i< costMap.size();i++) {boolean hasChange = false;for(int j =0; j< edges.length;j++) {Edge edge = edges[j];//该边起点目前总的路径大小int startPointCost = costMap.get(edge.getStartPoint()) == null ? 0:costMap.get(edge.getStartPoint());//该边终点目前总的路径大小int endPointCost = costMap.get(edge.getEndPoint()) == null ? Integer.MAX_VALUE : costMap.get(edge.getEndPoint());//如果该边终点目前的路径大小 > 该边起点的路径大小 + 该边权重 ,说明有更短的路径了if(endPointCost > (startPointCost + edge.getWeight())) {costMap.put(edge.getEndPoint(), startPointCost + edge.getWeight());parentMap.put(edge.getEndPoint(), edge.getStartPoint());hasChange = true;}}if (!hasChange) {//经常还没达到最大遍历次数便已经求出解了,此时可以优化为提前退出循环break;}}//在进行一次判断是否存在负环路boolean hasRing = false;for(int j =0; j< edges.length;j++) {Edge edge = edges[j];int startPointCost = costMap.get(edge.getStartPoint()) == null ? 0:costMap.get(edge.getStartPoint());int endPointCost = costMap.get(edge.getEndPoint()) == null ? Integer.MAX_VALUE : costMap.get(edge.getEndPoint());if(endPointCost > (startPointCost + edge.getWeight())) {System.out.print("\n图中存在负环路,无法求解\n");hasRing = true;break;}}if(!hasRing) {//打印出到各个节点的最短路径for(String key : costMap.keySet()) {System.out.print("\n到目标节点"+key+"最低耗费:"+costMap.get(key));if(parentMap.containsKey(key)) {List<String> pathList = new ArrayList<String>();String parentKey = parentMap.get(key);while (parentKey!=null) {pathList.add(0, parentKey);parentKey = parentMap.get(parentKey);}pathList.add(key);String path="";for(String k:pathList) {path = path.equals("") ? path : path + " --> ";path = path +  k ;}System.out.print(",路线为"+path);}}}}/***  代表"一条边"的信息对象** @author Administrator**/static class Edge{//起点idprivate String startPoint;//结束点idprivate String endPoint;//该边的权重private int weight;public Edge(String startPoint,String endPoint,int weight) {this.startPoint = startPoint;this.endPoint = endPoint;this.weight = weight;}public String getStartPoint() {return startPoint;}public String getEndPoint() {return endPoint;}public int getWeight() {return weight;}}}

五、小结

1、贝尔曼-福特算法Bellman–Ford主要用于存在负权重的方向图中(没有负权重也可以用,但是效率比狄克斯特拉算法低很多),搜索出源点到各个节点的最短路径

2、Bellman–Ford可以判断出图是否存在负环路,但存在负环路的情况下不支持计算出各个节点的最短路径。只需要在结束(节点数目-1)次遍历后,再执行一次遍历,若还可以更新数据则说明存在负环路

算法-贝尔曼-福特算法相关推荐

  1. JavaScript实现bellmanFord贝尔曼-福特算法(附完整源码)

    JavaScript实现bellmanFord贝尔曼-福特算法 bellmanFord.js完整源代码 bellmanFord.js完整源代码 export default function bell ...

  2. C++实现bellman ford贝尔曼-福特算法(最短路径)(附完整源码)

    C++实现bellman ford贝尔曼-福特算法 实现bellman ford贝尔曼-福特算法的完整源码(定义,实现,main函数测试) 实现bellman ford贝尔曼-福特算法的完整源码(定义 ...

  3. 算法系列——贝尔曼福特算法(Bellman-Ford)

    本系列旨在用简单的人话讲解算法,尽可能避免晦涩的定义,读者可以短时间内理解算法原理及应用细节.我在努力! 本篇文章编程语言为Python,供参考. 贝尔曼福特算法(Bellman-Ford) 典型最短 ...

  4. 贝尔曼-福特算法(Bellman-Ford)最短路径问题

    贝尔曼-福特算法(Bellman-Ford) 一.贝尔曼-福特算法(Bellman-Ford) 二.代码实现 一.贝尔曼-福特算法(Bellman-Ford) 贝尔曼-福特算法与迪科斯彻算法类似,都以 ...

  5. 了解贝尔曼·福特算法

    文章目录 为什么在现实生活中会有负权重的边? 为什么我们要留意负权重? 贝尔曼·福特算法如何工作 贝尔曼·福特伪码 Bellman Ford vs Dijkstra C示例 贝尔曼·福特算法的复杂度 ...

  6. Python实现迪杰斯特拉算法和贝尔曼福特算法求解最短路径

    文章目录 (一).题目 (二).导库 (三).绘制带权无向图 (四).获得最短路径 (四).实现最短路径高亮 (五).完整代码 (六).结果展示 关于Python数据分析在数学建模中的更多相关应用:P ...

  7. Bellman-Ford贝尔曼福特算法实现

    作为一种单源最短路径算法,Bellman-Ford对于有向图和无向图都能适用,它还有一个Dijkstra算法无法具备的特点,那就是对含负权图的最短路径搜索. 每i轮对边的遍历之后,只要不存在负权回路, ...

  8. 算法:贝尔曼-福特算法

    算法:贝尔曼-福特算法 1.简介 贝尔曼-福特算法(Bellman–Ford algorithm)是一个查找最短路径算法主要优点是支持负权重,但时间复杂度较高,还会有负权环的问题. 如果不需要权重应该 ...

  9. 算法/最短路径/Bellman-Ford贝尔曼福特算法

    ##问题描述 Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的.这时候,就需要使用其他的 ...

最新文章

  1. 青龙面板node-onebot 教程
  2. Source Insight 格式化
  3. ubuntu 18.04设置系统自带系统截图快捷键
  4. sysbench 压测 mysql_sysbench压测
  5. 千灯腾碧人潮涌,蓬勃“雨花”气如虹
  6. VS Supercharger插件的破解
  7. C语言学习之输出“魔方阵”。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。
  8. android多屏应用程序,微软也尝试“多屏协同” Windows系统可以运行安卓程序
  9. ajax登录非空判断,email ajax传输数据去重和非空判断(示例代码)
  10. Maximum upload size exceede上传文件大小超出解决
  11. Java语言学习概述
  12. 基于matlab 的燃油喷雾图像处理方法,基于MATLAB的燃油喷雾图像处理方法.doc
  13. 字符串转换到double数组
  14. python消息队列celery_python异步任务神器celery
  15. WAV音频格式解析C代码
  16. T-SQL语言(二)
  17. MM模块采购收货的错误解决方案(2)
  18. An NVIDIA kernel module ‘nvidia-drm‘ appears to already be loaded in your kernel...
  19. AMI码及HDB3码的编译码程序设计
  20. 数列求和再求极限问题

热门文章

  1. 微型计算机真无线耳机测评,真无线耳机测评
  2. 【无标题】三段大厂实习经历,我学到了什么?
  3. note_2020_3
  4. 如何使用Python批量下载图片
  5. 无线通信基础知识2:电磁波频谱的划分
  6. chapter16 性能调优与架构篇-基础理论和工具
  7. 基于Spring+SpringMVC+hibernate实现的体检中心管理系统
  8. 华为认证含金量如何?
  9. 计算机信息继续考试 d组教材,无为县“备好课”专题培训考核小结
  10. C语言开发服务器视频,C++游戏服务器开发视频教程