原来你是这样的迪杰斯特拉(迪杰斯塔拉 最短路径算法)

迪杰斯特拉算法

1.用途

我对这个大名鼎鼎的算法早有耳闻,在学习计算机网络的时候,更新路由表可以用这个算法.
它是一个非常好的计算图的最短路径的算法.

2.原理

划重点,迪杰斯特拉最最朴素的思想就是按长度递增的次序产生最短路径。即每次对所有可见点的路径长度进行排序后,选择一条最短的路径,这条路径就是对应顶点到源点的最短路径

Tips:可见点就是从源点开始按广度优先算法遍历顶点的过程中,搜索到的点。

下面来解释一下为什么源点到所有可见点的路径中长度最短的一条就一定是源点到该点的最短路径,会不会存在通过一些当前不可见的点间接到达该点的路径比它短呢?

我们设图G的顶点集合为V,再设一个集合S表示已求得最短路径的终点的集合(S怎么来的下面再说)。

设下一条最短路径(终点为x),那么它只能是弧(v,x)或者通过S中的顶点到达x即(v,vi,…,x)。我们来证明一下:
假设(v,…,x)路径上有一个顶点不在S中,则说明存在一条终点不在S中而长度比此路径还短的路径。但这是不可能的。因为我们按长度递增的顺序来产生各最短路径,所以长度比此路径还短的所有路径均已产生,他们的终点一定在S中。

3.步骤

  • 初始化一个集合,加入出发点
  • 找出集合中所有点的下一个点(该下一个点不在集合中),把最小的点加入集合
  • 重复以上步骤,直到没有新的点加入
  • 不在集合中的点距离设为无穷大

4. 编码

我这里并没有用集合来存储加入的节点,而是用一个数组存储所有点,其中未加入的点距离设置为无穷大

/**
	 * 
	 * @param graph
	 *            图
	 * @param start
	 *            出发点
	 * 
	 * @return 从出发点到各点的最短路径
	 */
	public int[] sortest(int[][] graph, int start) {

		final int N = graph.length;// 总共有N个点
		if (N == 0) {
			return null;
		}

		int[] minWay = new int[N];
		Arrays.fill(minWay, Integer.MAX_VALUE);// 初始化:最大距离填充

		minWay[start] = 0;// 出发点距离为0

		for (int i = 0; i < N - 1; i++) {
			// 每次加入一个新的地点 总共加N-1次

			int minDistance = Integer.MAX_VALUE;// 设置新加的点 距离为无穷大
			int addIndex = -1; // 设置新加的点 坐标为 -1

			for (int j = 0; minWay[j] != Integer.MAX_VALUE && j < N; j++) {
				// 遍历所有已加入点

				for (int k = 0; minWay[k] == Integer.MAX_VALUE && k < N; k++) {
					// 遍历所有以加入点的下一个点(要求该点未被访问)
					int nextDistance = graph[j][k] + minWay[j];

					if (nextDistance < minDistance) {
						// 如果该距离小于已知最小距离
						minDistance = nextDistance;
						addIndex = k;
					}
				}
			}

			if (addIndex != -1) {
				// 有新坐标加入 ,加入新坐标
				minWay[addIndex] = minDistance;
			} else {
				// 没有新的点加入了,结束循环
				break;
			}
		}

		return minWay;
	}

总结

迪杰斯特拉算法强化了BFS ,每次遍历只加入一个点,使得当存在环的时候最短路径不会出错.

参考文章

迪杰斯特拉(Dijkstra)算法最通俗易懂的讲解

你可能感兴趣的:(原来你是这样的迪杰斯特拉(迪杰斯塔拉 最短路径算法))