1. 程式人生 > >數學建模--迪克斯特拉( Dijkstra)演算法

數學建模--迪克斯特拉( Dijkstra)演算法

先貼上迪克斯特拉演算法的原理,該演算法又稱為PT標號法,對於演算法的定義和步驟比較難以理解,只需要粗略看一下就好。Dijkstra’s Algorithm 基本思想:
若給定帶權有向圖G=(V,E)和源頂點v0,構築一個源集合S,將v0加入其中。
① 對差集V\S中 個頂點vi,逐一計算從v0 至它的距離 D(v0 , vi ),若該兩頂點之間沒有邊,則其距離為無窮大。求出其中距離最短 的頂點w,將其加入到集合 S 中。
② 重新計算 v0 至差集 V\S 中各頂點的距離 D(v0, vi )= Min(D(v0, vi ), D(v0, w ) + C(w, vi )).其中C(w, vi )是頂點w 與 vi 之 間邊上的費用。
③ 重複 步驟①②。直至所有的頂點都加到集合S 中為止。
演算法結束時, 從 u0 到各頂點 v 的距離由 v 的最後一次的標號 l(v) 給出。 在 v 進入 Si
之前的標號 l(v) 叫 T 標號, v 進入 Si 時的標號 l(v) 叫 P 標號。演算法就是不斷修改各頂
點的 T 標號,直至獲得 P 標號。若在演算法執行過程中,將每一頂點獲得 P 標號所由來
的邊在圖上標明,則演算法結束時, u0 至各項點的最短路也在圖上標示出來了。
關於Dijkstra的演算法我推薦看一下中國民航學院的一個視訊,我把它儲存到百度雲,有興趣可以看看,連結:

http://pan.baidu.com/s/1jIDUnEQ 密碼: gbh2
下面直接貼上上matlab程式碼,該程式碼不是我原創的,我只是在原始碼上增加了註釋。

function [d index1 index2] = Dijkf(a)
%a 表示圖的權值矩陣
%d 表示所求最短路的權和
%index1 表示標號的頂點順序
%index2 表示標號頂點索引

M = max(max(a));
pb(1: length(a)) = 0;%初始化pb矩陣,清零
%該矩陣主要是用來標示矩陣d中P標號和T標號的分佈情況,
%為0則該點屬於T標號點,為1則該點屬於P標號點

%初始化起點
pb(1) = 1
; index1 = 1; index2 = ones(1, length(a)); d(1: length(a)) = M; d(1) = 0; temp = 1; while sum(pb) < length(a) tb = find(pb == 0);%找出未進行P標號即進行T標號的在d中的索引 d(tb) = min(d(tb), d(temp) + a(temp, tb));%T(v)=min(T(v),l(uv)+T(v)) tmpb = find(d(tb) == min(d(tb)));%tmpb等於T標號中的點的最小 值在d中的索引 temp = tb(tmpb(1
));%temp等於T標號的最小值第一個點在d中的索引 pb(temp) = 1;%將T標號的點進行P標號 index1 = [index1, temp];%將找到的temp加入到index1中,表示已經找到到底該點的最短路 index = index1(find(d(index1) == d(temp) - a(temp, index1)));%找出到達該點最短路徑中的前面的點 if length(index) >= 2 index = index(1);%取最前面的一個點新增到index2中 end index2(temp) = index; end d; index1; index2;

在這段程式碼中最難懂的是這行程式碼:

index = index1(find(d(index1) == d(temp) - a(temp, index1)));

首先是d(temp)表示最近被P標號的點距離起點的最短路徑,d(index1) 已經P標號的所有點的最短路徑,如果d(index1) == d(temp) - a(temp, index1))成立,這說明index1(1)是該最短路徑中到達點temp的前面一個點,反之則不是該路徑的點。
這裡寫圖片描述
下面通過上圖粗略解釋一下該程式碼的原理,首先假設在前面計算中點1 2 3 4都是index1中的點,從1到4的最短路徑是1-3-4,該路徑長為d(4),假設取index1中的2點(不是最短路徑的點),d(4)-a(2,4)~=d(3)(a(2,4)表示2-4的長),取index1中的3,d(4)-a(2,3) == d(3),所以3是該最短路徑上的點。