最短路徑之迪傑斯特拉算法的Java實現

  Dijkstra算法是最短路徑算法中爲人熟知的一種,是單起點全路徑算法。該算法被稱爲是「貪心算法」的成功典範。本文接下來將嘗試以最通俗的語言來介紹這個偉大的算法,並賦予java實現代碼。html

1、知識準備java

一、表示圖的數據結構算法

  用於存儲圖的數據結構有多種,本算法中筆者使用的是鄰接矩陣。數組

   圖的鄰接矩陣存儲方式是用兩個數組來表示圖。一個一維數組存儲圖中頂點信息,一個二維數組(鄰接矩陣)存儲圖中的邊或弧的信息。數據結構

  設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣,定義爲:性能

  

從上面能夠看出,無向圖的邊數組是一個對稱矩陣。所謂對稱矩陣就是n階矩陣的元知足aij = aji。即從矩陣的左上角到右下角的主對角線爲軸,右上角的元和左下角相對應的元全都是相等的。spa

    從這個矩陣中,很容易知道圖中的信息。htm

    (1)要判斷任意兩頂點是否有邊無邊就很容易了;blog

    (2)要知道某個頂點的度,其實就是這個頂點vi在鄰接矩陣中第i行或(第i列)的元素之和;隊列

    (3)求頂點vi的全部鄰接點就是將矩陣中第i行元素掃描一遍,arc[i][j]爲1就是鄰接點;

    而有向圖講究入度和出度,頂點vi的入度爲1,正好是第i列各數之和。頂點vi的出度爲2,即第i行的各數之和。

  有向圖的定義也相似,故不作贅述。

二、單起點全路徑

    所謂單起點全路徑,就是指在一個圖中,從一個起點出發,到全部節點的最短路徑。

 

三、圖論的基本知識(讀者需自行尋找相關資料)

 

四、互補鬆弛條件

 設標量d1,d2,....,dN知足

    dj<=di + aij,  (i,j)屬於A,

 且P是以i1爲起點ik爲終點的路,若是

    dj = di + aij, 對P的全部邊(i, j)

 成立,那麼P是從i1到ik的最短路。其中,知足上面兩式的被稱爲最短路問題的互補鬆弛條件。

2、算法思想

一、令G = (V,E)爲一個帶權無向圖。G中如有兩個相鄰的節點,i和j。aij(在這及其後面都表示爲下標,請注意)爲節點i到節點j的權值,在本算法能夠理解爲距離。每一個節點都有一個值di(節點標記)表示其從起點到它的某條路的距離。

  二、算法初始有一個數組V用於儲存未訪問節點的列表,咱們暫稱爲候選列表。選定節點1爲起始節點。開始時,節點1的d1=0, 其餘節點di=無窮大,V爲全部節點。
初始化條件後,而後開始迭代算法,直到V爲空集時中止。具體迭代步驟以下:

   將d值最小的節點di從候選列表中移除。(本例中V的數據結構採用的是優先隊列實現最小值出列,最好使用斐波那契對,在之前文章有過介紹,性能有大幅提示)。對於以該節點爲起點的每一條邊,不包括移除V的節點, (i, j)屬於A, 若dj > di + aij(違反鬆弛條件),則令

  dj = di + aij    , (若是j已經從V中移除過,說明其最小距離已經計算出,不參與這次計算)

  能夠看到在算法的運算工程中,節點的d值是單調不增的

  具體算法圖解以下

  

3、代碼實現

//接受一個有向圖的權重矩陣,和一個起點編號start(從0編號,頂點存在數組中)
	//返回一個int[] 數組,表示從start到它的最短路徑長度  
	public static int[] Dijsktra(int[][]weight,int start){
		int length = weight.length;
		int[] shortPath = new int[length];//存放從start到各個點的最短距離
		shortPath[0] = 0;//start到他自己的距離最短爲0
		String path[] = new String[length];//存放從start點到各點的最短路徑的字符串表示
		for(int i=0;i<length;i++){
			path[i] = start+"->"+i;
		}
		int visited[] = new int[length];//標記當前該頂點的最短路徑是否已經求出,1表示已經求出
		visited[0] = 1;//start點的最短距離已經求出
		for(int count = 1;count<length;count++){
			int k=-1;
			int dmin = Integer.MAX_VALUE;
			for(int i=0;i<length;i++){
				if(visited[i]==0 && weight[start][i]<dmin){
					dmin = weight[start][i];
					k=i;
				}
			}
			//選出一個距離start最近的未標記的頂點     將新選出的頂點標記爲以求出最短路徑,且到start的最短路徑爲dmin。
			shortPath[k] = dmin;
			visited[k] = 1;
			//以k爲中間點,修正從start到未訪問各點的距離
			for(int i=0;i<length;i++){
				if(visited[i]==0 && weight[start][k]+weight[k][i]<weight[start][i]){
					weight[start][i] = weight[start][k]+weight[k][i];
					path[i] = path[k]+"->"+i;
				}
			}
		}
		for(int i=0;i<length;i++){
			System.out.println("從"+start+"出發到"+i+"的最短路徑爲:"+path[i]+"="+shortPath[i]);
		}
		return shortPath;
		
	}

  這即是利用迪傑斯特拉算法實現最短路徑的方法。

以後能夠聲明一個常量,例如:

static final int MAX = 10000;

而後在main方法裏面建一個鄰接矩陣,調用此方法便可。

public static void main(String[] args) {
		int[][] weight = {
				{0,3,2000,7,MAX},
				{3,0,4,2,MAX},
				{MAX,4,0,5,4},
				{7,2,5,0,6},
				{MAX,MAX,4,6,0}
				};
		int start = 0;
		int[] dijsktra = Dijsktra(weight,start);
	}

  參考自:http://www.cnblogs.com/junyuhuang/p/4544747.html

相關文章
相關標籤/搜索