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