最短路徑之Dijkstra演算法

2021-08-26 02:27:37 字數 2160 閱讀 7106

這裡,我們想要得出節點a(節點1)到節點b(節點5)的最短路徑,就是怎麼走可以使得權重值的和最小,每一條邊都有乙個權重。

今天我們介紹的d演算法就是解決這類問題的,這是一種貪心演算法,每次只取權重和最小的點,通過不斷加入節點,來更新源節點a到各個節點的最短路徑,直到所有節點遍歷完。

演算法步驟:

1、定義,遍歷過的節點集合為s,集合u為其餘節點(即未遍歷)。初始時,s只包含源點v,即s=,v的距離為0。u包含除v外的其他頂點,即:u=。若v與u中頂點u有邊,則正常有權值,若u不是v的出邊鄰接點,則權值為∞。

注:這裡集合s、u,是為了判斷哪些節點已經遍歷過,如果u為空了,就不繼續執行。

2、從集合u中選取乙個距離v最小的頂點k,把k加入到s中。

3、以k為新考慮的中間點,修改v到u中各頂點的距離;若從源點v到頂點w的距離(經過頂點k)比原來距離(不經過頂點k)短,則修改v到w的距離值。

例子:

4、重複步驟2、3直到所有頂點都包含在s中。

1、初始化步驟

用乙個一維陣列dis來表示節點1到各個節點的最短路徑(即權重),沒有連線的用∞表示。除此之外,為了防止節點重複計算,我們把節點分成兩組,一組已經遍歷的節點集合s,另一組還沒遍歷集合u。初始化的時候,節點1在集合s中。

注:節點1到自己的權重為0。

2、從集合u中獲取離節點1最近的點(參考u在陣列中的最小值,是節點2),加入到集合s,並重新計算dis陣列。

(1)節點2有到節點3和4的邊,所以陣列dis的3和4位置的值可能會變動。

(2)2到3的權重為10,所以1到3的權重為17(7+10),17大於9,所以不用變動。

(3)3到4的權重為15,所以1到4的權重為22(7+15),22小於無窮,所以dis[4]=22。(這裡陣列角標大家注意下,dis[4]表示第四個位置,起始位置為1)

3、重複步驟2,獲取u裡面距離最近的點(這裡為節點3),重新計算dis陣列。

(1)節點3這裡和4、6有邊,所以dis的位置4、6可能需要修改值。(節點2在s中,只考慮u中沒遍歷過的節點)。

(2)3到4的權重為11,所以1到4的權重為20(9+11),小於22(dis[4]),所以dis[4]=20。

(3)3到6的權重為2,所以1到6的權重為11(9+2),小於14(dis[6]),所以dis[6]=11。

4、重複步驟2,取節點6加入s,重新計算dis。

節點6只有到5的邊了,所以只修改dis[6]的值。這裡節點1到節點5的權重為20(11+9),小於無窮(dis[5]),所以dis[5]=20。

5、繼續重複。

這次獲取到節點4,從dis陣列可以知道1到4的權重(20)已經大於等於1到5的權重(20),所以無論如何也無法從節點4取到權重更小的路徑了,所以可以捨棄(d演算法是無法解決負權重問題,所以圖的權重必須為正)。

由於節點1到節點5沒有邊連線,所以權重為無窮,大於20。所以,演算法的最終結果就是:

節點1到節點5的最短路徑是20,

順序是1->3->6->5。

有了演算法,必須要有**才有說服力,這裡我用c語言實現了d演算法的**,大家有興趣慢慢看,慢慢研究。我貼的是部分**,其他不重要**省略。

預定義變數:

資料初始化:

d演算法具體邏輯方法:

執行結果:

最短路徑 之Dijkstra演算法

dijkstra演算法dijkstra 鄰接矩陣 int n,e maxv maxv int dis maxv pre maxv pre用來標註當前結點的前乙個結點 bool vis maxv void dijkstra int s if u 1 return visit u true for in...

最短路徑 之Dijkstra演算法

dijkstra演算法 dijkstra 鄰接矩陣 int n,e maxv maxv int dis maxv pre maxv pre用來標註當前結點的前乙個結點 bool vis maxv void dijkstra int s if u 1 return visit u true for i...

最短路徑之Dijkstra演算法

using system namespace dijkstra演算法 路徑圖 static int places int math.sqrt map.length 獲取地點數 static int shortest new int places 存放從start到其他節點的最短路徑 static b...