1. 程式人生 > >最短距離----迪傑斯塔拉演算法----java版

最短距離----迪傑斯塔拉演算法----java版

原理(自己理解的,不當之處希望有人可以指出)

圖如上, 以求v0到v8頂點為例

首先求一下v0到各個頂點的距離,得到如下陣列

我們的目的就是根據上面的陣列確定v0到其他各個頂點的最短距離,這樣也就獲得了v0到v8的最短距離.

第一個可以確定最短距離的點

     從這個陣列我們可以知道v0到達v1的最短距離肯定是1,但是v0到v2的最短距離卻不一定是5

     為什麼這麼肯定呢??????????????

因為與v0直接連通的點就v1和v2這兩個點

     那麼v0到v1的最近距離要麼是v0直接到v1的距離:v0-->v1,要麼就是v0-->v2-->[....]-->v1的距離

    同理v0到v2的最近距離要麼是v0直接到v2的距離:v0-->v2,要麼就是v0-->v1-->[....]-->v2的距離

    由於v0-->v1的距離小於v0-->v2,因此v0直接到v1的距離為v0到v1的直接距離

    而對於v0-->v2的距離和v0-->v1-->[....]-->v2的距離並不能得到確定的判斷

由此我們找到了v0到v1的最短距離為1

第二個可以確定最短距離的點

那麼接著我們就從v0--->v1這條路繼續往下走,會得到下圖

由此我們找到了v0到v2的最短距離為4

    按照上訴思想,我們就可以找到v0到其他各個點的最短距離,當然假如只是為了找v0到某個點如v4,我們只要是v4這個點的最短距離確定了就可以結束上訴過程.

按照上訴思想我寫的程式碼如下:

package cn.nrsc.graph;

/**
 * @author 孫川 ---- 最短路徑---迪傑斯塔拉演算法(dijkstra)
 */

public class Graph_Dijkstra {

	// ----------------------------圖的表示方式------------------------
	private int vertexSize;// 頂點的數量
	private int[] vertexs;// 頂點對應的陣列
	private int[][] matrix;// 鄰接矩陣
	private static final int MAX_WEIGHT = 1000;// 代表頂點之間不連通
	private boolean[] isVisited; // 頂點是否已經被訪問

	public Graph_Dijkstra(int vertexSize) {
		this.vertexSize = vertexSize;
		this.matrix = new int[vertexSize][vertexSize];
		this.vertexs = new int[vertexSize];
		for (int i = 0; i < vertexSize; i++) {
			vertexs[i] = i;
		}

		isVisited = new boolean[vertexSize];
	}
	// ----------------------------圖的表示方式------------------------

	// 最短距離----迪傑斯塔拉演算法 start--->end之間的最短距離
	public void dijkstra(int start, int end) {
		// 自己到自己的距離為0
		if (start == end) {
			System.out.println(start + "到" + end + "的最短距離為:" + 0);
			return;
		}

		// 首先計算出start到圖中其他各個頂點的距離
		int[] distance = new int[vertexSize];
		// start到其他各個點的距離
		for (int i = 0; i < vertexSize; i++)
			distance[i] = matrix[start][i];

		// 記錄已經確認點的Id,如果是end就可以結束迴圈了
		int targetId = 0;
		// 記錄start到該點是否為最短距離
		boolean[] isMinPath = new boolean[vertexSize];
		// 到自身的最短距離肯定獲取到了
		isMinPath[start] = true;

		// 迪傑斯塔拉演算法的思想是利用distance陣列確認出start到圖中任意一個點的最短距離
		// 一次只能確認start到一個點的最短距離,並且不知道什麼時候會確認了到end點的距離,
		// 所以我們需要讓他一個點一個點的去確認, 直到end點確認了就可以退出迴圈了
		// 最壞的情況下由start到end需要確認的次數是vertexSize-1次
		for (int j = 1; j < vertexSize; j++) { // 外層控制確認的次數---最壞情況下為n-1次

			int min = MAX_WEIGHT; // 先假設最小距離為MAX_WEIGHT

			// distance陣列中的最小值為start到它的最短距離 ----- 這裡必須得好好理解一下(看我寫的原理部分)

			// 找到distance陣列中的最小值
			for (int k = 0; k < vertexSize; k++) {

				if (distance[k] < min && !isMinPath[k]) {
					min = distance[k];
					targetId = k;
				}
			}

			// 確定了start到targetId的最短距離
			System.out.println(start + "到" + targetId + "的最短距離為:" + min);
			// 在是否獲得最短距離陣列中進行標記
			isMinPath[targetId] = true;

			// 如果targetId = end了就說明找到了start到end的最短距離
			if (targetId == end)
				break;

			// 以min這條路繼續往下走,找到start到不確定點更小的距離----迴圈後,不確定點中的最小值,將可以被確定
			for (int w = 0; w < vertexSize; w++)
				if (!isMinPath[w] && min + matrix[targetId][w] < distance[w])
					distance[w] = min + matrix[targetId][w];

		}
		// 列印一下--start到各個點的最短距離

		// for (int i = 0; i < vertexSize; i++)
		// System.out.print(" " + distance[i]);
	}

	public static void main(String[] args) {
		Graph_Dijkstra graph = new Graph_Dijkstra(9);
		int[] v0 = { 0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
		int[] v1 = { 1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
		int[] v2 = { 5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
		int[] v3 = { MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT };
		int[] v4 = { MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT };
		int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT };
		int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7 };
		int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4 };
		int[] v8 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 0 };

		graph.matrix[0] = v0;
		graph.matrix[1] = v1;
		graph.matrix[2] = v2;
		graph.matrix[3] = v3;
		graph.matrix[4] = v4;
		graph.matrix[5] = v5;
		graph.matrix[6] = v6;
		graph.matrix[7] = v7;
		graph.matrix[8] = v8;

		graph.dijkstra(0, 8);
		System.out.println("---------------------");
		graph.dijkstra(8, 0);
		
	}
}

貼上一下列印結果: