單願最短路徑描述:給定帶權有向圖G=(V,E),其中每條邊的權是非負實數。另外,還給定V中的一個頂點,稱之爲源(origin)。如今要計算從源到其餘各頂點的最短路徑的長度。這裏的路徑長度指的是到達路徑各邊權值之和。算法
Dijkstra算法是解單源最短路徑問題的貪心算法。Dijkstra算法的基本思想是:設置頂點集合S並不斷地作貪心選擇來擴充集合。一個頂點屬於集合S當且僅當從源點到該頂點的最短路徑長度已知。貪心擴充就是不斷在集合S中添加新的元素(頂點)。
初始時,集合S中僅含有源(origin)一個元素。設curr是G的某個頂點,把從源到curr且中間只通過集合S中頂點的路稱之爲從源到頂點curr的特殊路徑,而且使用數組distance記錄當前每一個頂點所對應的最短路徑的長度。Dijkstra算法每次從圖G中的(V-S)的集合中選取具備最短路徑的頂點curr,並將curr加入到集合S中,同時對數組distance進行必要的修改。一旦S包含了全部的V中元素,distance數組就記錄了從源(origin)到其餘頂點的最短路徑長度。 c#
核心代碼:
Dijkstra描述:帶權有向圖G=(V,E),V={1,2,3,...}。頂點origin是源。數組distance[index]表示當前源到頂點index的最短路徑長度。數組prev[index]表示源點到達index頂點最短路徑的前一個頂點[Dijkstra只能獲取最短路徑的長度,經過prev記錄前驅頂點能夠很方便的獲取詳細的最短路徑]。
數據結構與代碼:數組
public struct DIJGraph { public int[] vexs; public int[][] arcs; public int num; } public static bool DIJKSTRA(int origin,DIJGraph g,int[] distance,int[] prev) { if (origin < 0 || origin >= g.num) return false; bool[] s = new bool[g.num]; for (int index = 0; index < g.num; ++index) { s[index] = false; distance[index] = g.arcs[origin][index]; prev[index] = (distance[index] == Int32.MaxValue) ? -1 : origin; } distance[origin] = 0; s[origin] = true; for (int i = 0; i < g.num; ++i) { int temp = Int32.MaxValue; int curr = 0; for (int index = 0; index < g.num; ++index) { if (!s[index] && distance[index] < temp) { curr = index; temp = distance[index]; } } s[curr] = true; for (int index = 0; index < g.num; ++index) { if (!s[index] && g.arcs[curr][index] < Int32.MaxValue) { int newDistance = distance[curr] + g.arcs[curr][index]; if (newDistance < distance[index]) { distance[index] = newDistance; prev[index] = curr; } } } } return true; }
貪心選擇性質|最優子結構性質是Dijkstra算法所具有的。不過,雖然Dijkstra算法是解決單源最短路徑的一款很優秀的算法,可是若是在圖中存在多條最短路徑,Dijkstra算法只能獲取路徑的長度,而沒法給出最短路徑的詳細狀況。即便在代碼中添加distance[index]表示當前源到頂點index的最短路徑長度。數組prev[index]來記錄前驅點,可是一旦存在多條最短路徑,咱們只能獲取最早遇到的那條(或者最後遇到的那條路徑)[每每,咱們偏向於獲取的是最短路線而非路長]。總之,Dijkstra算法還有許多改進的地方。
本文提供的核心代碼使用C#實現,您能夠點擊下載獲取源代碼[點擊下載C語言實現代碼]。網絡