這裡,我們想要得出節點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...