文章目录

  • 为什么在现实生活中会有负权重的边?
  • 为什么我们要留意负权重?
  • 贝尔曼·福特算法如何工作
  • 贝尔曼·福特伪码
  • Bellman Ford vs Dijkstra
  • C示例
  • 贝尔曼·福特算法的复杂度
    • 时间复杂度
  • 空间复杂度
  • 贝尔曼·福特算法应用
  • 参考文档

    Bellman-Ford算法有助于我们找到加权图中从一个顶点到所有其他顶点的最短路径。
    它与Dijkstra算法相似,但可用于边具有负权重的图。

为什么在现实生活中会有负权重的边?

    负权重边一开始似乎没用,但它们可以解释许多现象,如现金流、化学反应中释放/吸收的热量等。
    例如,如果从一种化学物质A到达另一种化学物质B的方法不同,则每种方法都会具有散热和吸热的副反应。
    如果我们想找到一组需要最小能量的反应,那么我们需要将吸热作为负权重,将散热作为正权重。

为什么我们要留意负权重?

    负权重边可以创建负权重循环,即通过返回到同一点来减少总路径距离的循环。

    当试图找出最短路径时,负权重循环可能会给出错误的结果
    最短路径算法,如Dijkstra的算法,不能检测到这样的循环,可能会给出一个不正确的结果,因为他们可以使用负权重循环,并减少路径长度。

贝尔曼·福特算法如何工作

    Bellman-Ford算法的工作原理是高估从起始顶点到所有其他顶点的路径长度。然后,它通过找到更短的新路径来逐步调整先前的估计。
    通过对所有顶点重复执行此操作,我们可以保证结果得到优化。
    第一步,从权重图开始。

    第二步,选择一个顶点,将其他顶点的路径值赋值为无穷大。

    第三步,访问每个节点,如果路径距离不正确,则进行修正。

    第四步,我们要做5次,因为在最差情况下,一个顶点的路径长度需要被重新调整5次。

    第五步,注意右上方角落的定点是如何调整路径长度的。

    第六步,当所有顶点都有路径长度后,我们检查是否存在负循环。

贝尔曼·福特伪码

    我们需要维持每个顶点的路径距离。我们可以将其存储在一个大小为v的数组中,其中v是顶点的数目。
    我们还希望能够获得最短路径,不仅知道最短路径的长度。为此,我们将每个顶点映射到最后更新其路径长度的顶点。
    一旦算法结束,我们就可以从目标顶点回溯到源顶点来找到路径。

function bellmanFord(G, S)for each vertex V in Gdistance[V] <- infiniteprevious[V] <- NULLdistance[S] <- 0for each vertex V in G                for each edge (U,V) in GtempDistance <- distance[U] + edge_weight(U, V)if tempDistance < distance[V]distance[V] <- tempDistanceprevious[V] <- Ufor each edge (U,V) in GIf distance[U] + edge_weight(U, V) < distance[V}Error: Negative Cycle Existsreturn distance[], previous[]
Bellman Ford vs Dijkstra

    Bellman-Ford算法和Dijkstra算法在结构上非常相似。虽然Dijkstra只查看顶点的直接邻居,但Bellman在每次迭代中都会遍历每一条边。

C示例
// Bellman Ford Algorithm in C#include <stdio.h>
#include <stdlib.h>#define INFINITY 99999//struct for the edges of the graph
struct Edge {int u;  //start vertex of the edgeint v;  //end vertex of the edgeint w;  //weight of the edge (u,v)
};//Graph - it consists of edges
struct Graph {int V;        //total number of vertices in the graphint E;        //total number of edges in the graphstruct Edge *edge;  //array of edges
};void bellmanford(struct Graph *g, int source);
void display(int arr[], int size);int main(void) {//create graphstruct Graph *g = (struct Graph *)malloc(sizeof(struct Graph));g->V = 4;  //total verticesg->E = 5;  //total edges//array of edges for graphg->edge = (struct Edge *)malloc(g->E * sizeof(struct Edge));//------- adding the edges of the graph/*edge(u, v)where    u = start vertex of the edge (u,v)v = end vertex of the edge (u,v)w is the weight of the edge (u,v)*///edge 0 --> 1g->edge[0].u = 0;g->edge[0].v = 1;g->edge[0].w = 5;//edge 0 --> 2g->edge[1].u = 0;g->edge[1].v = 2;g->edge[1].w = 4;//edge 1 --> 3g->edge[2].u = 1;g->edge[2].v = 3;g->edge[2].w = 3;//edge 2 --> 1g->edge[3].u = 2;g->edge[3].v = 1;g->edge[3].w = 6;//edge 3 --> 2g->edge[4].u = 3;g->edge[4].v = 2;g->edge[4].w = 2;bellmanford(g, 0);  //0 is the source vertexreturn 0;
}void bellmanford(struct Graph *g, int source) {//variablesint i, j, u, v, w;//total vertex in the graph gint tV = g->V;//total edge in the graph gint tE = g->E;//distance array//size equal to the number of vertices of the graph gint d[tV];//predecessor array//size equal to the number of vertices of the graph gint p[tV];//step 1: fill the distance array and predecessor arrayfor (i = 0; i < tV; i++) {d[i] = INFINITY;p[i] = 0;}//mark the source vertexd[source] = 0;//step 2: relax edges |V| - 1 timesfor (i = 1; i <= tV - 1; i++) {for (j = 0; j < tE; j++) {//get the edge datau = g->edge[j].u;v = g->edge[j].v;w = g->edge[j].w;if (d[u] != INFINITY && d[v] > d[u] + w) {d[v] = d[u] + w;p[v] = u;}}}//step 3: detect negative cycle//if value changes then we have a negative cycle in the graph//and we cannot find the shortest distancesfor (i = 0; i < tE; i++) {u = g->edge[i].u;v = g->edge[i].v;w = g->edge[i].w;if (d[u] != INFINITY && d[v] > d[u] + w) {printf("Negative weight cycle detected!\n");return;}}//No negative weight cycle found!//print the distance and predecessor arrayprintf("Distance array: ");display(d, tV);printf("Predecessor array: ");display(p, tV);
}void display(int arr[], int size) {int i;for (i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");
}
贝尔曼·福特算法的复杂度
时间复杂度
最佳案例复杂度 O(E)
平均情况复杂度 O(VE)
最坏情况的复杂度 O(VE)
空间复杂度

    空间复杂度为O(V)。

贝尔曼·福特算法应用
  1. 用于计算路由算法中的最短路径
  2. 寻找最短路径
参考文档

[1]Parewa Labs Pvt. Ltd.Bellman Ford’s Algorithm[EB/OL].https://www.programiz.com/dsa/bellman-ford-algorithm,2020-01-01.

了解贝尔曼·福特算法相关推荐

  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 algorithm )用于计算出起点到各个节点的最短距离,支 ...

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

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

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

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

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

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

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

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

最新文章

  1. 给妹子讲python-S01E15详解python迭代环境
  2. Python入门100题 | 第029题
  3. XebiaLabs DevOps平台推出软件发布风险和合规性管理功能
  4. 2019年关于VM和Kubernetes的思考 | 技术头条
  5. 视频: 安卓连接无线临时网络adhoc共享电脑上网无需adhoc补丁
  6. 计算机视觉实习面经【微软/阿里/腾讯】
  7. SELECT语句选项
  8. 卷积交织/解交织C++程序
  9. [android] 手机卫士保存安全号码
  10. GPT Plus Money!B O O M
  11. echarts源码打包_Echarts模块v1.5更新【更新支持多线程,封装大量快速方法,增加史上最详细示例】...
  12. WinRAR 5.60 官方简体中文无广告弹窗版本
  13. Zigbee协议网络相关的东西(1)
  14. android n改铃声,来电铃声自定义,我”响“你快乐!
  15. linux电脑滚轮不能用,图文详解电脑鼠标滚轮不动了怎么办_电脑鼠标滚轮不能用的三种解决方法-系统城...
  16. [PYTHON]python编程100例
  17. contiki学习心路历程
  18. vimdesktop --goreliu 版本配置
  19. weboffice使用
  20. 印度区块链项目Matic Network的应用场景分析

热门文章

  1. 人口流向数据_各省全国各省人口净流入数据:浙江、广东、新疆、重庆成宠儿...
  2. 带你Java入门(Java系列1)
  3. Unity3D Animator人物模型下沉的一种原因
  4. 穆利堂[推荐]河南郑州房地产CRM管理系统软件整体解决方案.穆穆-movno1
  5. vue 下载文件流和捕获后端返回的状态码和错误信息的方法
  6. jquery开关灯案例_jQuery实现开关灯效果
  7. 文本识别 OCR 浅析:特征篇
  8. PHP之50个开源项目
  9. android自带的webview有广告,android webview 拦截广告
  10. 电脑开机蓝屏怎么解决?3个方法,快速解决电脑蓝屏