最短路dijkstra算法詳解:dijkstra(圖解)

最短路DijkStra’s Algorithm算法詳解

dijkstra(圖解)

在這裏插入圖片描述

概念:

Weight[m,n]: 二維數組,代表節點m到節點n的權重,即圖上每條邊的權重值.

WeightMin[n]: 一維數組,代表從開始節點0到節點n的已知通路上,所有已計算的權重之和的最小值.用來存放每一次計算的最小值.

FinalSet:已經確認的最終節點的集合

圖上數據說明: 節點從左上點到右下點,從左到右從上到下,座標從0開始到8

Weight[m,n]數據如下

n0 n1 n2 n3 n4 n5 n6 n7 n8
n0 2 9 6
n1 1
n2 4 6
n3 4
n4 2 9 7
n5 5 1
n6 5
n7 1 5
n8

算法基本原理

基礎原理其實很直白樸素,就是從開始節點起,計算所有能到達終止節點的通路的距離。從這些通路中找尋權重和最小的那一條通路。

不過這種樸素的找法隨着節點數增加由於組合爆炸的原因,計算複雜度是呈階乘級上升的,比指數級還恐怖.

然後在這個原理的基礎上做一下優化,因爲對於到達之前某個節點的最短距離已經確定了之後,我們可以該節點的最短距離存起來,當計算它之後的節點通路時,就直接拿出來用,而不需要再重頭計算之前的那些節點。

優化後的算法只做2件事

【P1】第一,不斷運行【廣度優先算法】,優先找到最接近源點的所有可見點(能與已知節點直接連通的點),計算這些可見點到源點的距離長度,由於一個節點可能有多條通路,所以當計算該點到源點的另一條通路的距離長度時,要與之前的WeightMin[n]取最小值然後再更新。

【P2】第二,每當運行完單次【廣度優先算法】後,使用【貪心算法】,從所有已知路徑中選擇長度最短的那條路徑,將頂點歸入最終節點集合裏FinalSet裏,然後再從該節點運行【廣度優先算法】,直至圖裏所有點都進入FinalSet裏。

【貪心算法】保證了進入FinalSet裏的節點距離一定是能到達該點的所有路徑中最短的,不可能有其他到達該點更短的距離。

【廣度優先算法】保證了在每次選擇路徑時,都能找到最短的一條路徑。

流程開始:

圖1

將所有節點權重和WeightMin[]更新爲無窮大,暫時以99代替(因爲所有節點權重和都沒有比99更大的,可以用來代替無窮大)。

【P1】初始條件,從自己到自己的權重爲0,WeightMin[0]=0,其餘都是99。

【P2】將節點0歸入最終節點集合裏FinalSet裏,FinalSet[]={0},此時FinalSet未包含全部節點,所以即將對節點0運行【廣度優先算法】

圖2

【P1】對節點0運行【廣度優先算法】,計算其所有可見點(n1,n3,n4)這3點到源點的通路的距離長度(使用已知的WeightMin[0]加上其直接連接的各邊的權重Weight[0,(n1,n3,n4)]),分別是[0+2,0+9,0+6]。然後與之前的WeightMin[[1,3,4]]:[99,99,99]進行比較,取最小值(2<99,9<99,6<99)然後再更新,所以最後這3點的WeightMin[[1,3,4]]=[2,9,6]。

【P2】從所有已知路徑頂點n1(2),n3(9),n4(6)中找長度最短的那條的頂點n1(即節點1),將其納入最終節點集合FinalSet={0,1},此時FinalSet未包含全部節點,所以即將對節點1運行【廣度優先算法】

圖3

【P1】對節點1運行【廣度優先算法】,計算其所有可見點(n2,n4)到源點的通路的距離長度WeightMin[1]+Weight[1,(n2,n4)]=[2+1,2+3]。然後與之前的WeightMin[[2,4]:[99,6]進行比較更新,WeightMin[[2,4]]=[3,5]。

【P2】從所有已知路徑頂點n2(3),n3(9),n4(5)中找長度最短的那條的頂點n2,將其納入最終節點集合FinalSet={0,1,2},此時FinalSet未包含全部節點,所以即將對進來的節點2運行【廣度優先算法】

在這裏插入圖片描述

圖4

【P1】對節點2運行【廣度優先算法】,計算其所有可見點(n4,n6)到源點的通路的距離長度WeightMin[2]+Weight[1,(n4,n6)]=[3+1,3+6]。然後與之前的WeightMin[[4,6]:[5,99]進行比較更新,WeightMin[[4,6]=[4,9]。

【P2】從所有已知路徑頂點n3(9),n4(4),n6(9)中找長度最短的那條的頂點n4,將其納入最終節點集合FinalSet={0,1,2,4},此時FinalSet未包含全部節點,所以即將對進來的節點4運行【廣度優先算法】

圖5

【P1】對上次歸入FinalSet的節點運行【廣度優先算法】求所有可見點的距離長度

g(n4) => (n3,n5,n7)

w(n3,n5,n7)=WeightMin[4]+Weight[4,(n3,n5,n7)]=[4+2,4+9,4+7]=[6,13,11]

WeightMin[[3,5,7]] = min([6,13,11] ,WeightMin[[3,5,7]]) = min([6,13,11] ,[9,99,99])=[6,13,11]

【P2】從所有已知路徑頂點(=上一次全部頂點 - 上一次選中頂點 + 本次可見點)中選出長度最短的那條的頂點,歸入FinalSet

min{n3,n5,n6,n7} = min{WeightMin[[3,5,6,7]]}=min([6,13,9,11])=6

n3

FinalSet={0,1,2,3,4}

圖6

【P1】對上次歸入FinalSet的節點運行【廣度優先算法】求所有可見點的距離長度

g(n3) => (n7)

w(n7) = WeightMin[3]+Weight[3,(n7)] = [6+4] = [10]

WeightMin[7] = min([10] ,WeightMin[7]) = min([10] ,[11]) = [10]

【P2】在所有已知路徑中選出最短路徑對應的節點,歸入FinalSet

min{n5,n6,n7} = min{WeightMin[[5,6,7]]} = min([13,9,10]) = 9

n6

FinalSet={0,1,2,3,4,6}

在這裏插入圖片描述

圖7

【P1】對上次歸入FinalSet的節點運行【廣度優先算法】求所有可見點的距離長度

g(n6) => (n8)

w(n8) = WeightMin[6]+Weight[6,(n8)] = [9+5] = [14]

WeightMin[8] = min([14] ,WeightMin[8]) = min([14] ,[99]) = [14]

【P2】在所有已知路徑中選出最短路徑對應的節點,歸入FinalSet

min{n5,n7,n8} = min{WeightMin[[5,7,8]]} = min([13,10,14]) = 10

n7

FinalSet={0,1,2,3,4,6,7}

圖8

【P1】對上次歸入FinalSet的節點運行【廣度優先算法】求所有可見點的距離長度

g(n7) => (n5,n8)

w(n5,n8) = WeightMin[7]+Weight[7,(n5,n8)] = [10+1,10+5] = [11,15]

WeightMin[[5,8]] = min([11,15] ,WeightMin[[5,8]]) = min([11,15] ,[13,14]) = [11,14]

【P2】在所有已知路徑中選出最短路徑對應的節點,歸入FinalSet

min{n5,n8} = min{WeightMin[[5,8]]} = min([11,14]) = 11

n5

FinalSet={0,1,2,3,4,6,7,5}

圖9

【P1】對上次歸入FinalSet的節點運行【廣度優先算法】求所有可見點的距離長度

g(n5) => (n8)

w(n8) = WeightMin[5]+Weight[5,(n8)] = [11+1] = [12]

WeightMin[8] = min([12] ,WeightMin[8]) = min([12] ,[14]) = [12]

【P2】在所有已知路徑中選出最短路徑對應的節點,歸入FinalSet

min{n8} = min{WeightMin[8]} = min([12]) = 12

n8

FinalSet={0,1,2,3,4,6,7,5,8}

至此,所有節點都進入FinalSet裏

算法終止

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章