Bellman-Ford算法GydF4y2Ba
这个GydF4y2Ba贝尔曼-福特算法GydF4y2Ba是A.GydF4y2Ba图形GydF4y2Ba搜索算法找到给定源顶点和图表中的所有其他顶点之间的最短路径。该算法可用于加权和未加权的图形。GydF4y2Ba
喜欢GydF4y2BaDijkstra的最短路径算法GydF4y2Ba,Bellman-Ford算法保证在图中找到最短路径。虽然它比Dijkstra的算法慢,但Bellman-Ford能够处理包含负边缘权重的图形,因此它更加多样化。值得注意的是,如果图表中存在负周期,则没有最短路径。绕过负周期,无限次数将继续降低路径的成本(即使路径长度正在增加)。因此,Bellman-Ford还可以检测到作为一个有用特征的负循环。GydF4y2Ba
想象一个场景,你需要从家里去看棒球比赛。一路上,每一条路上都会发生两件事中的一件。首先,有时你使用的道路是收费道路,你必须支付一定的费用。其次,有时你认识的人住在那条街上(比如家人或朋友)。那些人可以给你钱来帮你重新装钱包。你需要穿过城市,你想带着尽可能多的钱穿过城市,这样你就可以买热狗了。鉴于你知道哪些道路是收费道路,哪些道路有人可以给你钱,你可以使用贝尔曼福特帮助规划最佳路线。GydF4y2Ba
而不是你的家,一个棒球比赛和街道,无论是从你那里拿钱还是给你钱,贝尔曼福特看着加权图。该图是连接图中的不同顶点的边的集合,就像道路一样。边缘对它们具有成本。无论是积极的成本(如收费)或负成本(就像一个会给你钱的朋友)。所以,在上面的图形中,一个红色的箭头意味着你必须支付钱来使用那条路,绿色箭头意味着你可以获得钱来使用那条路。在图表中,源顶点是您的家,目标顶点是棒球体育场。在那里,您希望最大限度地提高所采取的负加权边的数量和绝对值。相反,您希望最小化您采取的正加权边的数量和值。Bellman-Ford这样做。GydF4y2Ba
内容GydF4y2Ba
概述GydF4y2Ba
Bellman-Ford算法在输入图上运行,GydF4y2Ba , 和GydF4y2Ba 顶点和GydF4y2Ba 边缘。单个源顶点,GydF4y2Ba 也必须提供,因为Bellman-Ford算法是单源最短路径算法。但是,无需提供目标顶点,因为Bellman-Ford计算了最短的距离GydF4y2Ba全部GydF4y2Ba从源顶点的图表中的顶点。GydF4y2Ba
贝尔曼福特算法,如GydF4y2BaDijkstra算法GydF4y2Ba,使用原理GydF4y2Ba放松GydF4y2Ba找到越来越准确的路径长度。但是,贝尔曼福特,用这个过程解决两个主要问题: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
循环将图形中的每个顶点的距离设置为无穷大。稍后将源顶点更改为等于零。也在第一次GydF4y2Ba为了GydF4y2Ba
循环,这GydF4y2BaPGydF4y2Ba
每个顶点的值都设置为“无”。该值是指向前置顶点的指针,以便稍后创建路径。GydF4y2Ba
下一个GydF4y2Ba为了GydF4y2Ba
循环只是通过每个边缘GydF4y2Ba(紫外线)GydF4y2Ba
在GydF4y2BaEGydF4y2Ba
和GydF4y2Ba放松一下GydF4y2Ba它。这个过程已经完成GydF4y2Ba|五|- 1GydF4y2Ba
时代。GydF4y2Ba
松弛方程GydF4y2Ba
放松是贝尔曼福特最重要的一步。它可以提高到任何给定顶点的距离的精度。松弛通过不断缩短顶点之间的计算距离来工作,将该距离与其他已知距离进行比较。GydF4y2Ba
以前面的棒球为例。比方说,我认为到棒球场的距离是20英里。然而,我知道体育场前拐角处的距离是10英里,我知道从拐角处到体育场的距离是1英里。很明显,从我到体育场的距离是GydF4y2Ba顶多GydF4y2Ba11英里。所以,我可以更新我的信念来反映这一点。这是一个放松的一个循环,它已经完成,直到找到最短路径。GydF4y2Ba
这是弛豫方程。GydF4y2Ba
放松方程式GydF4y2Ba
1 2 3 4GydF4y2Ba放松(u,v):如果v.distance>u.distance+weight(u,v):v.distance=u.distance+weight(u,v)v.p=uGydF4y2Ba
请记住,到源顶点以外的每个顶点的距离都从无穷远开始,因此此算法的明确起点是源顶点之外的边。假设有一条边从源顶点出来,GydF4y2Ba
,到另一个顶点,GydF4y2Ba
.这个边缘的重量为5.所以,GydF4y2Ba如果GydF4y2Ba
放松功能中的声明看起来像是这样的GydF4y2Ba
这与GydF4y2Ba
由于这当然是真的,因此执行其余函数。GydF4y2BaA.Distance.GydF4y2Ba
设置为5,并且GydF4y2BaA.GydF4y2Ba
被设定为GydF4y2BasGydF4y2Ba
,源顶点。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第2步GydF4y2Ba,如果我们回到所有的边缘,我们应该看到所有的GydF4y2Ba 在GydF4y2Ba ,GydF4y2Ba .贝尔曼福特只会报告一个负周期GydF4y2Ba ,因此在负重循环中没有任何错误报告。GydF4y2Ba
如果存在负重循环,那么该循环的一个边缘可以GydF4y2Ba总是GydF4y2Ba放松(因为它可以随着我们围绕循环而减少)。想象有问题的边缘是边缘GydF4y2Ba 这意味着GydF4y2Ba 实际上会小于GydF4y2Ba ,它将触发负周期报告。GydF4y2Ba
复杂性GydF4y2Ba
如上所述GydF4y2Ba在上面GydF4y2Ba,Bellman-Ford制作GydF4y2Ba 每次迭代都放松,有GydF4y2Ba 迭代。因此,最坏的情况是贝尔曼·福特公司在GydF4y2Ba 时间。GydF4y2Ba
但是,在某些情况下,迭代的数量可能会低得多。对于某些图表,只需要一个迭代,因此在最佳案例方案中GydF4y2Ba 需要时间。只需要一轮放松只需要一轮放松的图形是一个图,其中每个顶点只能以线性方式连接到下一个图形,如下面的图形:GydF4y2Ba
另见:GydF4y2Ba大o符号GydF4y2Ba.GydF4y2Ba
最差GydF4y2Ba | 最好的GydF4y2Ba | |
贝尔曼福特GydF4y2Ba |
应用程序GydF4y2Ba
Bellman-Ford的版本用于距离矢量路由协议。该协议决定如何在网络上路由数据数据包。距离方程(在网络中决定权重)是路由器的数量,一定路径必须通过以到达其目的地。GydF4y2Ba
对于互联网,具体而言,有许多协议使用Bellman-Ford。一个示例是路由信息协议。这是最古老的Internet协议之一,它通过限制跳数可以在进入目的地的路上进行跳数来防止循环。第二示例是内部网关路由协议。此专有协议用于帮助计算机在系统中交换路由数据。GydF4y2Ba