1.算法适用情况
1.1 这个算法适用于图中有负权值的边的最短路径的计算
2.2 这个算法可以用来判断图中是否有总权值为负的环存在
2.算法思想
2.1 算法是对图中的边集进行操作的,这和Dijkstra算法不同
2.2 算法是从源节点来进行广度搜索并完成最短路径的建立的
2.3 算法需要执行|V|-1次的大循环,以此来确保找到|V|-1个最短路径。每个循环中是对所有边的一个小循环操作。因此时间复杂度为O(|V|*|E|)。每次大循环必定会找到大于等于一个节点的最短路径
2.4 执行完|V|-1次大循环后,跳出。下面再执行一次循环,如果有权值为负的环存在的话,你的比较条件会成立,返回判断值就行了。而dist[]数组中存的就是你的执行当前次数下时候的源点到各个点的最短路径。注意,如果最后结果中有正无穷的数存在(或者是自己设置的比较大的数),那么说明s到这个点是不可达的。
3.算法伪代码
bool Bellman-Ford(G,w,s) //图G ,边集 函数 w ,s为源点
for each vertex v ∈ V(G): //初始化距离源点距离均为无穷大
d[v] ←+∞
d[s] ←0 //源点距离自身为0
for i = 1 → |V|: //松弛操作需要重复多次
for each edge (u,v) ∈ E(G):
if d[v] > d[u] + l(u,v):
d[v] = d[u] + l(u,v)
for each edge(u,v) ∈ E(G): //判断是否存在负权环路
if d[v] > d[u] + l(u,v):
return false
return true
4.算法优化
4.1 算法可以进行一个优化,设置一个标志位,如果下一次大循环时候,标志位没有改变,说明当前的dist[]数组已经都是源点到各个点的最短路径了,而且因为是提前完成了任务,说明一定不存在负环。
4.2 你也可以引入parent数组来记录你的每个点的前驱节点是谁,相应的数组更新操作应该在比较条件成立的时候进行。输出最短路径经过的节点的时候直接迭代输出parent就行了。
4.3 算法可以用队列优化,但是资料显示队列优化的时候不能适应所有情况,所以不阐述了。s
5.算法性能
5.1 算法时间复杂度为O(|V|*|E|),比Dijkstra算法的一般要慢。(其实主要看你的优化算法)
5.2 算法书写比较简单,核心就是两个循环,一个比较条件。