图的最短路径算法——Bellman-Ford算法的java实现

Bellman-Ford算法和Dijkstra算法都是求解图的最短路径的算法。

两者区别在于:Dijkstra要求图中不存在边权值之和为负数的环路,否则算法无法收敛;Bellman-Ford算法可以检测出图中是否存在权值之和为负数的环路。

下文中用到的Graph类参见博文

package algorithm;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import matrix.Graph;

public class ShortestPath {

	int origin;
	int[] preNodes;
	double[] distances;
	boolean hasNegativeLoop;

	public ShortestPath(int o, double[] dis, int[] pre, boolean has) {
		origin = o;
		preNodes = pre;
		distances = dis;
		hasNegativeLoop = has;
	}

	// 返回 o 到 d 的最短路程
	static double Dijkstra(Graph g, int origin, int destination) {
		return Dijkstra(g, origin).distances[destination];
	}

	// 返回 o 到所有节点的最短路程
	static ShortestPath Dijkstra(Graph g, int origin) {
		int nodeNum = g.getNodeNum();

		// 初始化前向节点
		int pre[] = new int[nodeNum];
		pre[origin] = origin;

		// 初始化距离向量
		double[] distances = new double[nodeNum];
		for (int i = 0; i < nodeNum; ++i) {
			distances[i] = Graph.INF;
		}
		distances[origin] = 0;

		// 初始化候选顶点集,即为起始节点
		Set<Integer> V = new HashSet<Integer>();
		V.add(Integer.valueOf(origin));

		while (!V.isEmpty()) {

			// 选出 V 中距离起点最近的节点,从V中删除
			Integer toRemove = null;

			double minDisInV = Graph.INF;
			for (Integer i : V) {
				if (distances[i] <= minDisInV) {
					minDisInV = distances[i];
					toRemove = i;
				}
			}
			V.remove(toRemove);

			// 在与toRemove的出边相连的节点中,选择节点 j
			Map<Integer, Object> outEdges = g.getOutEdges(toRemove);
			if (outEdges != null) {
				for (Integer j : outEdges.keySet()) {
					// 如果节点 j 可以使得距离向量更小,把 j 加入 V
					if (distances[j] > distances[toRemove] + (double) outEdges.get(j)) {
						distances[j] = distances[toRemove] + (double) outEdges.get(j);
						pre[j] = toRemove;
						if (!V.contains(j)) {
							V.add(j);
						}
					}
				}
			}
		}

		return new ShortestPath(origin, distances, pre, false);
	}

	// 返回 o 到所有节点的最短路程
	static ShortestPath BellmanFord(Graph g, int origin) {
		int nodeNum = g.getNodeNum();
		boolean hasNLoop = false;

		// 初始化前向节点
		int pre[] = new int[nodeNum];
		pre[origin] = origin;

		// 初始化距离向量
		double[] distances = new double[nodeNum];
		for (int i = 0; i < nodeNum; ++i) {
			distances[i] = Graph.INF;
		}
		distances[origin] = 0;

		int iteration = nodeNum;
		while (iteration-- > 0) {
			boolean update = false;
			// 遍历所有的边
			for (int i = 0; i < nodeNum; ++i) {
				Map<Integer, Object> outEdges = g.getOutEdges(i);
				if (outEdges != null) {
					for (Integer j : outEdges.keySet()) {
						// 如果节点 j 可以使得距离向量更小,把 j 加入 V
						if (distances[j] > distances[i] + (double) outEdges.get(j)) {
							update = true;
							if (iteration == 0) {
								hasNLoop = true;
								break;
							}
							distances[j] = distances[i] + (double) outEdges.get(j);
							pre[j] = i;
						}
					}
				}
			}
			// 如果这次遍历没有任何更新,那么下一次也不会更新,提前退出循环
			if (!update) {
				break;
			}
		}
		return new ShortestPath(origin, distances, pre, hasNLoop);
	}

	public void analyse() {
		System.out.println("Negative loops exist: " + hasNegativeLoop);
		for (int i = 0; i < distances.length; ++i) {
			String c = distances[i] < Graph.INF ? String.valueOf(distances[i]) : "inf";
			System.out.println("Distance from " + origin + " to " + i + ": " + c);
			if (distances[i] < Graph.INF) {
				int j = i;
				while (j != origin) {
					System.out.print(j + " <= ");
					j = preNodes[j];
				}
				System.out.println(j);
			}
		}
	}

来看小例子:

	
	public static void main(String[] args) {
		Graph g = new Graph(6,false);
		double[][] triples = {
				{1,2,2},
				{2,1,-3},
				{1,3,1},
				{2,3,1},
				{3,2,1},
				{2,4,1},
				{3,4,3},
				{2,5,0},
				{4,5,0}
				};
		g.addEdges(triples);
		g.show();
		
		ShortestPath sp = ShortestPath.BellmanFord(g, 1);
		//ShortestPath sp = ShortestPath.Dijkstra(g, 1);
		
		System.out.println();
		sp.analyse();
		

	}

}

图中存在负环是显然的,因为有 {1,2,2} 和 {2,1,-3}。

运行结果:

0.0 inf inf inf inf inf 
inf 0.0 2.0 1.0 inf inf 
inf -3.0 0.0 1.0 1.0 0.0 
inf inf 1.0 0.0 3.0 inf 
inf inf inf inf 0.0 0.0 
inf inf inf inf inf 0.0 

If negative loops exist: true
Distance from 1 to 0: inf
Distance from 1 to 1: -6.0
1
Distance from 1 to 2: -3.0
2 <= 1
Distance from 1 to 3: -4.0
3 <= 1
Distance from 1 to 4: -2.0
4 <= 2 <= 1
Distance from 1 to 5: -3.0
5 <= 2 <= 1

可以看出,只要一直循环下去,所有距离都会趋于负无穷。比如循环次数再翻一倍时:

If negative loops exist: true
Distance from 1 to 0: inf
Distance from 1 to 1: -12.0
1
Distance from 1 to 2: -9.0
2 <= 1
Distance from 1 to 3: -10.0
3 <= 1
Distance from 1 to 4: -8.0
4 <= 2 <= 1
Distance from 1 to 5: -9.0
5 <= 2 <= 1

事实上,只要重复 1=>2=>1=>2=>… 就会使总路程数不断减少。

来一个规模大一点的例子,节点数1000,边数100000:

		int N = 1000;
		Random rand = new Random();
		Graph g = new Graph(N,false);
		for(int i = 1; i<100000; ++i) {
			g.addEdge(rand.nextInt(N),rand.nextInt(N),rand.nextDouble());
		}
		//g.show();
		
		long begintime = System.nanoTime();
		
		ShortestPath sp = ShortestPath.BellmanFord(g, 1);
		//ShortestPath sp = ShortestPath.Dijkstra(g, 1);
		
		long endtime = System.nanoTime();
		
		System.out.println();
		sp.analyse();

		long costTime = (endtime - begintime)/1000000;
		System.out.println("Time used: "+costTime);

结果:


Negative loops exist: false
Distance from 1 to 0: 0.1178139809154638
0 <= 212 <= 690 <= 213 <= 856 <= 89 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 1: 0.0
1
Distance from 1 to 2: 0.08065859993706903
2 <= 649 <= 669 <= 648 <= 633 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 3: 0.08116689820549627
3 <= 648 <= 633 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 4: 0.07111204888545863
4 <= 936 <= 563 <= 183 <= 449 <= 1
Distance from 1 to 5: 0.08827929338718277
5 <= 672 <= 527 <= 1
Distance from 1 to 6: 0.08270874263714678
6 <= 646 <= 973 <= 693 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 7: 0.06916873694425418
7 <= 484 <= 765 <= 973 <= 693 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 8: 0.10939175185848171
8 <= 364 <= 308 <= 199 <= 139 <= 670 <= 192 <= 527 <= 1
Distance from 1 to 9: 0.0783899669706094
9 <= 440 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 10: 0.10397438373195189
10 <= 511 <= 973 <= 693 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 11: 0.11045791932386517
11 <= 597 <= 551 <= 440 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 12: 0.0834832517606845
12 <= 594 <= 646 <= 973 <= 693 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 13: 0.06632569195821614
13 <= 236 <= 494 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 14: 0.10684510424753724
14 <= 63 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 15: 0.08256547299665895
15 <= 420 <= 697 <= 645 <= 262 <= 124 <= 580 <= 900 <= 839 <= 781 <= 527 <= 1
Distance from 1 to 16: 0.1096329758525515
16 <= 706 <= 768 <= 487 <= 695 <= 211 <= 99 <= 527 <= 1
Distance from 1 to 17: 0.07537571922046005
17 <= 911 <= 262 <= 124 <= 580 <= 900 <= 839 <= 781 <= 527 <= 1
Distance from 1 to 18: 0.09925216239038415
18 <= 827 <= 32 <= 856 <= 89 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 19: 0.09683672016487854
19 <= 229 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 20: 0.07427699189492398
20 <= 357 <= 484 <= 765 <= 973 <= 693 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 21: 0.07783416800299692
21 <= 793 <= 733 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 22: 0.07238442992454519
22 <= 839 <= 781 <= 527 <= 1
Distance from 1 to 23: 0.10495390887155953
23 <= 843 <= 182 <= 937 <= 504 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 24: 0.05879953933073656
24 <= 937 <= 504 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 25: 0.0641243897072653
25 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 26: 0.1085529028004284
26 <= 238 <= 352 <= 962 <= 351 <= 38 <= 948 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 27: 0.0899738066585356
27 <= 157 <= 594 <= 646 <= 973 <= 693 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 28: 0.0999880744962669
28 <= 409 <= 169 <= 869 <= 593 <= 494 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 29: 0.06865435688074473
29 <= 755 <= 595 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 30: 0.07711943673683253
30 <= 296 <= 677 <= 831 <= 113 <= 935 <= 211 <= 99 <= 527 <= 1
Distance from 1 to 31: 0.07994800205405383
31 <= 807 <= 837 <= 311 <= 527 <= 1
Distance from 1 to 32: 0.061525207871197085
32 <= 856 <= 89 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 33: 0.08460781199640222
33 <= 688 <= 631 <= 657 <= 148 <= 727 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 34: 0.02890762140659775
34 <= 527 <= 1
Distance from 1 to 35: 0.1046550946041277
35 <= 977 <= 702 <= 53 <= 570 <= 837 <= 311 <= 527 <= 1
Distance from 1 to 36: 0.13133006328285102
36 <= 975 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 37: 0.056090552427294105
37 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 38: 0.061921084222054334
38 <= 948 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 39: 0.06717751235710434
39 <= 464 <= 124 <= 580 <= 900 <= 839 <= 781 <= 527 <= 1
Distance from 1 to 40: 0.11382708513290962
40 <= 947 <= 440 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 41: 0.1295413711710246
41 <= 817 <= 124 <= 580 <= 900 <= 839 <= 781 <= 527 <= 1
Distance from 1 to 42: 0.09663809457384731
42 <= 260 <= 115 <= 105 <= 925 <= 222 <= 100 <= 99 <= 527 <= 1
Distance from 1 to 43: 0.10171582504910237
43 <= 633 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 44: 0.09501074073877458
44 <= 253 <= 89 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 45: 0.07479613246873362
45 <= 660 <= 206 <= 451 <= 755 <= 595 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 46: 0.06866370335208771
46 <= 29 <= 755 <= 595 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 47: 0.0807521297774576
47 <= 986 <= 231 <= 648 <= 633 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 48: 0.05191128475116591
48 <= 199 <= 139 <= 670 <= 192 <= 527 <= 1
Distance from 1 to 49: 0.09988621914030427
49 <= 965 <= 907 <= 629 <= 755 <= 595 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 50: 0.08745823185614554
50 <= 60 <= 789 <= 651 <= 211 <= 99 <= 527 <= 1
Distance from 1 to 51: 0.11407297028631058
51 <= 928 <= 450 <= 182 <= 937 <= 504 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 52: 0.061169794677373046
52 <= 979 <= 416 <= 1
Distance from 1 to 53: 0.06555191782814462
53 <= 570 <= 837 <= 311 <= 527 <= 1
Distance from 1 to 54: 0.08523879526475608
54 <= 148 <= 727 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 55: 0.06897354633883912
55 <= 37 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 56: 0.08177961186258864
56 <= 100 <= 99 <= 527 <= 1
Distance from 1 to 57: 0.07589364300347312
57 <= 297 <= 633 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 58: 0.09853633153153618
58 <= 730 <= 742 <= 510 <= 952 <= 39 <= 464 <= 124 <= 580 <= 900 <= 839 <= 781 <= 527 <= 1
Distance from 1 to 59: 0.09660177072593423
59 <= 950 <= 678 <= 416 <= 1
Distance from 1 to 60: 0.0783128445194986
60 <= 789 <= 651 <= 211 <= 99 <= 527 <= 1
Distance from 1 to 61: 0.08470638910659423
61 <= 468 <= 446 <= 236 <= 494 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 62: 0.10259684812334335
62 <= 370 <= 572 <= 590 <= 670 <= 192 <= 527 <= 1
Distance from 1 to 63: 0.06518156347888071
63 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 64: 0.07437738917311543
64 <= 629 <= 755 <= 595 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 65: 0.09820819272133674
65 <= 325 <= 577 <= 97 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 66: 0.10305719662831214
66 <= 59 <= 950 <= 678 <= 416 <= 1
Distance from 1 to 67: 0.07217736502084782
67 <= 968 <= 52 <= 979 <= 416 <= 1
Distance from 1 to 68: 0.05390701339738624
68 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 69: 0.14212211421884402
69 <= 449 <= 1
Distance from 1 to 70: 0.08397070309308208
70 <= 763 <= 63 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 71: 0.07922755905933787
71 <= 394 <= 449 <= 1
Distance from 1 to 72: 0.10215072660794733
72 <= 769 <= 231 <= 648 <= 633 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 73: 0.10804506653056112
73 <= 66 <= 59 <= 950 <= 678 <= 416 <= 1
Distance from 1 to 74: 0.040248223002147476
74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 75: 0.0728479934920101
75 <= 569 <= 580 <= 900 <= 839 <= 781 <= 527 <= 1

此处略去1800行……

Distance from 1 to 975: 0.04934329085366129
975 <= 173 <= 192 <= 527 <= 1
Distance from 1 to 976: 0.0959283679740528
976 <= 481 <= 605 <= 733 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 977: 0.08984512197925976
977 <= 702 <= 53 <= 570 <= 837 <= 311 <= 527 <= 1
Distance from 1 to 978: 0.08561735049702224
978 <= 467 <= 161 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 979: 0.04707597617645698
979 <= 416 <= 1
Distance from 1 to 980: 0.08035283111667768
980 <= 934 <= 104 <= 416 <= 1
Distance from 1 to 981: 0.07975587841442533
981 <= 791 <= 88 <= 987 <= 190 <= 133 <= 68 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 982: 0.07812479259437066
982 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 983: 0.0868834962372359
983 <= 564 <= 342 <= 494 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 984: 0.11375195012192885
984 <= 367 <= 631 <= 657 <= 148 <= 727 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 985: 0.08272028915519736
985 <= 987 <= 190 <= 133 <= 68 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 986: 0.07275958862760723
986 <= 231 <= 648 <= 633 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 987: 0.06923073127552015
987 <= 190 <= 133 <= 68 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 988: 0.0770690343585757
988 <= 694 <= 48 <= 199 <= 139 <= 670 <= 192 <= 527 <= 1
Distance from 1 to 989: 0.09581754395677411
989 <= 865 <= 340 <= 148 <= 727 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 990: 0.06217346784414157
990 <= 615 <= 835 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 991: 0.09813339143101862
991 <= 606 <= 547 <= 738 <= 556 <= 240 <= 642 <= 38 <= 948 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 992: 0.10363541184241176
992 <= 976 <= 481 <= 605 <= 733 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 993: 0.11613209524413759
993 <= 618 <= 350 <= 267 <= 450 <= 182 <= 937 <= 504 <= 729 <= 781 <= 527 <= 1
Distance from 1 to 994: 0.10590106175797098
994 <= 961 <= 608 <= 990 <= 615 <= 835 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 995: 0.08245117830714233
995 <= 793 <= 733 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 996: 0.08243467703191232
996 <= 490 <= 218 <= 755 <= 595 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 997: 0.07808150350591492
997 <= 37 <= 228 <= 422 <= 103 <= 781 <= 527 <= 1
Distance from 1 to 998: 0.10833415588585826
998 <= 965 <= 907 <= 629 <= 755 <= 595 <= 74 <= 123 <= 34 <= 527 <= 1
Distance from 1 to 999: 0.08559650731829094
999 <= 603 <= 897 <= 74 <= 123 <= 34 <= 527 <= 1
Time used: 487

刺激吧!只用了487ms!

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/itnerd/article/details/83042711
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞