bellman算法GydF4y2Ba
这GydF4y2BaBellman-Ford算法GydF4y2Ba是一个GydF4y2Ba图GydF4y2Ba在给定的源顶点和图中所有其他顶点之间找到最短路径的搜索算法。该算法既适用于加权图,也适用于非加权图。GydF4y2Ba
就像GydF4y2BaDijkstra最短路径算法GydF4y2Ba, Bellman-Ford算法保证能在图中找到最短路径。尽管Bellman-Ford算法比Dijkstra算法慢,但它能够处理包含负边权的图,因此它更加通用。值得注意的是,如果图中存在一个负循环,那么就不存在最短路径。沿着负循环无限次会继续降低路径成本(即使路径长度在增加)。正因为如此,Bellman-Ford还可以检测负循环,这是一个有用的特性。GydF4y2Ba
想象一下,您需要从您家到棒球比赛的场景。一路上,在每条道路上,可能发生两件事之一。首先,有时你正在使用的道路是一个收费路,你必须支付一定数量的钱。其次,有时候你知道生活在那条街上(如家庭成员或朋友)。那些人可以给你钱来帮助你补充钱包。你需要跨越城里,你想尽可能多地抵乡,所以你可以买热狗。鉴于你知道哪条道路是通行费,哪条道路有能给你钱的人,你可以使用Bellman-Ford来帮助计划最佳路线。GydF4y2Ba
Bellman-Ford观察的不是你的家,不是棒球比赛,不是从你那里拿走钱或给你钱的街道,而是一个加权图。图是连接图中不同顶点的边的集合,就像道路一样。这些边是有代价的。要么是正成本(如通行费),要么是负成本(如朋友会给你钱)。在上面的图表中,红色箭头表示你需要花钱才能使用这条路,绿色箭头表示你需要花钱才能使用这条路。在图中,源顶点是你的家,目标顶点是棒球场。在这个过程中,你想要最大化负加权边的数量和绝对值。相反地,你想要最小化正加权边的数量和值。Bellman-Ford就是这么做的。GydF4y2Ba
内容GydF4y2Ba
概述GydF4y2Ba
Bellman-Ford算法作用于输入图,GydF4y2Ba ,GydF4y2Ba 顶点,GydF4y2Ba 边缘。单个源顶点,GydF4y2Ba ,因为Bellman-Ford算法是一种单源最短路径算法。但是,不需要提供目标顶点,因为Bellman-Ford计算的是到目的地的最短距离GydF4y2Ba所有GydF4y2Ba图中来自源顶点的顶点。GydF4y2Ba
Bellman-Ford算法GydF4y2Badijkstra的算法GydF4y2Ba,使用的原则GydF4y2Ba松弛GydF4y2Ba找到越来越精确的路径长度。不过,Bellman-Ford在这个过程中解决了两个主要问题:GydF4y2Ba
- 如果存在负重循环,则搜索最短路径将永远持续下去。GydF4y2Ba
- 选择一个糟糕的松弛顺序会导致指数松弛。GydF4y2Ba
的检测GydF4y2Ba消极的周期GydF4y2Ba是重要的,但该算法的主要贡献在于松弛的排序。Dijkstra算法是GydF4y2Ba贪婪算法GydF4y2Ba选择最近的未被处理的顶点。另一方面,Bellman-Ford放松了GydF4y2Ba所有GydF4y2Ba的边缘。GydF4y2Ba
Bellman-Ford标记了图的边GydF4y2Ba 作为GydF4y2Ba
这组边是完全松弛的GydF4y2Ba 时代,在那里GydF4y2Ba 为图中顶点的数目。GydF4y2Ba
算法Psuedo-codeGydF4y2Ba
Bellman-Ford算法的伪代码非常短。GydF4y2Ba
这是用伪代码编写的Bellman-Ford的高级描述,而不是一个实现。GydF4y2Ba
1 2 3 4 5 6 7GydF4y2Ba |
|
第一个GydF4y2Ba为GydF4y2Ba
Loop将图中每个顶点的距离设置为无穷大。稍后,源顶点将更改为0。在第一次GydF4y2Ba为GydF4y2Ba
循环,GydF4y2BaP.GydF4y2Ba
每个顶点的值都设置为任何内容。此值是指向前任顶点的指针,以便我们稍后可以创建路径。GydF4y2Ba
下一个GydF4y2Ba为GydF4y2Ba
循环只是通过每条边GydF4y2Ba(u, v)GydF4y2Ba
在GydF4y2BaE.GydF4y2Ba
和GydF4y2Ba放松GydF4y2Ba它。这个过程完成了GydF4y2Ba| | V - 1GydF4y2Ba
时代。GydF4y2Ba
放松方程式GydF4y2Ba
放松是Bellman-Ford中最重要的一步。这是将距离的准确性提高到任何给定顶点的准确性。放松通过不断缩短顶点之间的计算距离,比较与其他已知距离的距离之间的计算距离。GydF4y2Ba
从早些时候拿棒球例子。假设我认为与棒球体育场的距离是20英里。但是,我知道在体育场前到角落的距离是10英里,我知道从角落到体育场,距离是1英里。显然,与我到体育场的距离是GydF4y2Ba最多GydF4y2Ba11英里。因此,我可以更新我的信念来反映这一点。这是一个松弛的循环,不断重复直到找到最短路径。GydF4y2Ba
这是放松方程。GydF4y2Ba
放松方程GydF4y2Ba
1 2 3 4GydF4y2Ba放松(U,V):如果v.distance> u.distance +重量(u,v):v.distance = u.distance +重量(u,v)v.p = uGydF4y2Ba
请记住,除了源之外的每个顶点的距离在Infinity开始,因此该算法的明确起点是源顶点的边缘。想象一下,源顶点有一个边缘,GydF4y2Ba
,到另一个顶点,GydF4y2Ba
.这条边的权值是5。所以,GydF4y2Ba如果GydF4y2Ba
松弛函数中的表述对于这条边是这样的GydF4y2Ba
哪个和GydF4y2Ba
因为这当然是正确的,所以函数的其余部分将被执行。GydF4y2BaA.distanceGydF4y2Ba
被设置为5,并且前身GydF4y2Ba一种GydF4y2Ba
被设置为GydF4y2BaS.GydF4y2Ba
,源顶点。GydF4y2Ba
放松是安全的,因为它遵守GydF4y2Ba三角不等式GydF4y2Ba的另一种说法是“去的最近的距离”GydF4y2Ba 到GydF4y2Ba 到GydF4y2Ba 应该小于或等于到达的最短距离吗GydF4y2Ba 到GydF4y2Ba 加上最短距离GydF4y2Ba 到GydF4y2Ba “:GydF4y2Ba
检测负周期GydF4y2Ba
对于Bellman-Ford算法的一个非常简单和简单的补充可以允许它检测负周期,这是非常重要的,因为它不允许完全最短的路径查找。在显示的Bellman-Ford算法之后GydF4y2Ba以上GydF4y2Ba已经运行,需要一个更多的短环来检查负重循环。GydF4y2Ba
此伪代码被写入算法的高级描述,而不是实现。GydF4y2Ba
1 2 3 4 5 6 7 8 9 10GydF4y2Ba |
|
算法的证明GydF4y2Ba
证明Bellman-Ford有几个简短的步骤。第一步表明,Bellman-Ford的每次迭代以适当的方式降低了每个顶点的距离。第二步示出,一旦算法终止,如果没有负重循环,则产生的距离是完全正确的。最后的步骤表明,如果不是这种情况,那么确实存在负重循环,这证明了贝尔曼 - 福特负周期检测。GydF4y2Ba
步骤1:GydF4y2Ba
索赔:GydF4y2Ba在交互影响GydF4y2Ba ,尽管GydF4y2Ba 在GydF4y2Ba 那GydF4y2Ba 最多是每条路径的权值吗GydF4y2Ba 到GydF4y2Ba 使用最多的GydF4y2Ba 边缘。GydF4y2Ba
在迭代之前GydF4y2Ba , 的价值GydF4y2Ba 是否受下列方程约束GydF4y2Ba
在哪里GydF4y2Ba 是给定路径的重量和GydF4y2Ba 是那条路径上的边数。随后的松弛只会减少GydF4y2Ba ,所以这将永远保持真实。这GydF4y2Ba 迭代将考虑所有传入的边缘GydF4y2Ba 的路径GydF4y2Ba 边缘。GydF4y2Ba
步骤2:GydF4y2Ba
索赔:GydF4y2Ba如果输入图没有任何负权环,那么Bellman-Ford将准确地给出到每个顶点的距离GydF4y2Ba 在图表中从来源。GydF4y2Ba
重要的是要注意的是,没有负重循环,最短的路径将永远很简单。没有任何重复的边缘。所以,每个最短的路径都有GydF4y2Ba 顶点,GydF4y2Ba 边缘(取决于我们计算距离的顶点)。更普遍,GydF4y2Ba ,所以每条路径都有GydF4y2Ba 顶点,GydF4y2Ba 边缘。GydF4y2Ba
考虑从GydF4y2Ba 到GydF4y2Ba ,在那里GydF4y2Ba 是GydF4y2Ba .在这方面GydF4y2Ba 迭代,我们发现了最短的路径GydF4y2Ba 到GydF4y2Ba 使用最多的GydF4y2Ba 边缘。GydF4y2Ba 在这个路径的重量。所以,GydF4y2Ba 最多是距离吗GydF4y2Ba 到GydF4y2Ba .在这方面GydF4y2Ba 迭代,我们所做的只是比较GydF4y2Ba 到GydF4y2Ba .唯一可能发生的就是GydF4y2Ba 变小。所以,后GydF4y2Ba 迭代,GydF4y2Ba 最多是距离吗GydF4y2Ba 到GydF4y2Ba .因为它不可能是真的GydF4y2Ba小GydF4y2Ba而不是来自最短的路径GydF4y2Ba 到GydF4y2Ba ,是完全相等的。GydF4y2Ba
第3步:GydF4y2Ba
索赔:GydF4y2BaBellman-Ford可以报告负权环。GydF4y2Ba
使用我们的GydF4y2Ba步骤2GydF4y2Ba,如果我们返回所有边缘,我们应该看到所有人GydF4y2Ba 在GydF4y2Ba 那GydF4y2Ba .Bellman-Ford只有在GydF4y2Ba ,所以不可能有任何关于负权环的虚假报告。GydF4y2Ba
如果有一个负权环,那么这个环的一条边可以GydF4y2Ba总是GydF4y2Ba放松(因为它会在循环过程中不断减少)。假设这条边就是那条边GydF4y2Ba 这意味着GydF4y2Ba 实际会小于GydF4y2Ba ,这将触发一个负面循环报告。GydF4y2Ba
复杂GydF4y2Ba
所述GydF4y2Ba以上GydF4y2Ba, bellman使GydF4y2Ba 每次迭代都可以放松,确实如此GydF4y2Ba 迭代。因此,最坏的情况是Bellman-Ford运行GydF4y2Ba 时间。GydF4y2Ba
然而,在某些场景中,迭代的次数可能要低得多。对于某些图,只需要一次迭代,因此在最好的情况下,只需要一次GydF4y2Ba 时间是必要的。一个只需要一轮松弛的图的例子是一个图,其中每个顶点只以线性方式连接到下一个顶点,如下图所示:GydF4y2Ba
也可以看看:GydF4y2Ba大O符号GydF4y2Ba.GydF4y2Ba
最糟糕的GydF4y2Ba | 最好的事物GydF4y2Ba | |
bellmanGydF4y2Ba |
应用程序GydF4y2Ba
距离矢量路由协议使用Bellman-Ford的一个版本。该协议决定如何在网络上路由数据包。距离方程(决定网络中的权重)是某条路径到达目的地必须经过的路由器数量。GydF4y2Ba
特别是对于Internet,有许多协议使用Bellman-Ford。一个例子是路由信息协议。这是最古老的互联网协议之一,它通过限制数据包在到达目的地的路上的跳数来防止循环。第二个例子是内部网关路由协议。这个专有协议用于帮助机器在系统中交换路由数据。GydF4y2Ba