1. 程式人生 > >[matlab] 22.matlab圖論實例 最短路問題與最小生成樹 (轉載)

[matlab] 22.matlab圖論實例 最短路問題與最小生成樹 (轉載)

dijkstra 分享 data 幫助 存儲 生成樹 jks lap open

最短路問題之 Floyd

某公司在六個城市 c1c1,c2c2,….,c6c6 中有分公司,從 cici 到 cjcj 的直接航程票價記在下述矩陣的 (ii,jj) 位置上。 (∞表示無直接航路),請幫助該公司設計一張城市 c1c1 到其它城市間的票價便宜的路線圖。

技術分享圖片

變量解釋:

  • n 是公司個數
  • a 存儲航路票價,最後結束循環存儲的是最便宜票價
  • path 存儲每對頂點之間最短路徑上所經過的定點的序號,也就是”中轉站”序號
技術分享圖片
clear;clc;
n = 6;      
a = [0 50 inf 40 25 10;
        0 0 
15 20 inf 25; 0 0 0 10 20 inf; 0 0 0 0 10 25; 0 0 0 0 0 55; 0 0 0 0 0 0]; % 由於 a 是無向圖,航路票價沿著正對角線對稱,可以只寫出右上角 a = a + a; % 由於票價沿正對角線對稱,即完整的 a 為 a + a 的轉置 path = zeros(6); % 定義 path 為 6 x 6 的矩陣 for k = 1:n for i = 1:n for j = 1:n if a(i,j) > a(i,k) + a(k,j)
% 如果從 i 城市到 j 城市的票價大於從 i 城市到 k,再從 k 到 j 城,那麽 i 到 j 城肯定不是最短路徑 a(i,j) = a(i,k) + a(k,j); % 更新 i 到 j 的最少票價 path(i,j) = k; % 同時記錄下 i 到 j 的"中轉站" % 註意下一次更新會覆蓋上一次 path(i,j) 存儲的,所以其實 path(i,j)中存儲的 只是最後一個 "中轉站" end end end end a,path
Floyd 算法

技術分享圖片

最短路問題之 dijkstra 算法

變量解釋:

  • n 是公司個數
  • m 存儲票價
  • pb 存放標號信息,當 pb(ii) = 1,當前第 ii 節點已標號,否則為 0 未標號
  • d 表示最短通路的值
  • path 存儲每對頂點之間最短路徑上所經過的定點的序號
  • tb 表示當前未標記的點的矩陣
  • fb 表示當前已標記的點的矩陣
  • min 求最小值之前的預設值
  • lastpoint 暫存當前選定的一個已標記點
  • newpoint 暫存當前選定的一個未標記點
  • plus 即已知點到未知點距離
技術分享圖片
clear;clc;
n = 6;
m = [0 50 inf 40 25 10;
     0 0 15 20 inf 25;
     0 0 0 10 20 inf;
     0 0 0 0 10 25;
     0 0 0 0 0 55;
     0 0 0 0 0 0];
 m = m + m;
 pb(1:length(m))= 0; % 將所有未標記點置 0
 pb(1) = 1;    % 選擇第 1 個點標記
 d(1:length(m))=0;  % 將全部最短距離置 0
 path(1:length(m))=0;   % 將全部"中轉站"置 0 
 while sum(pb) < 6  % 當狀態不全為 1(即未標記全部點時)
     tb = find(pb==0);   % 找到未標記的點的矩陣
     fb = find(pb==1);   % 找到已標記的點的矩陣
     min = 1000000;    
     lastpoint =1;    
     newpoint =1; 
     % 從每一個已標記點,到每一個未標記點
     for i=1:length(fb)   
         for j=1:length(tb) 
             plus = d(fb(i)) + m(fb(i),tb(j));  % 計算點之間的距離
             if min > plus
                min = plus;  % 更新最小值
                lastpoint = fb(i);   % 記錄當前最小值下已標記點
                newpoint = tb(j);    % 記錄當前最小值下未標記點
             end
         end
     end
     d(newpoint) = min;   % 更新最終的最小值
     pb(newpoint) = 1;    % 更新當前未標記點狀態(未標記——》標記)
     path(newpoint) = lastpoint;  % 更新當前點上一個點
 end
 d,path
dijkstra 算法

技術分享圖片

最小生成樹問題之prim

技術分享圖片

變量解釋:

  • n 頂點個數
  • a 存儲圖
  • result 第一、二、三行分別表示生成樹邊的起點、終點、權集合
  • p 存放圖的最小生成樹中的頂點
  • tb 存放當前未選擇的頂點
  • temp 存放當前最小生成樹連通的所有邊
  • d 存放最小的邊值
  • jb 存放最小的邊值中已經選作最小生成樹的點的矩陣(也許不止一個)
  • kb 存放最小的邊值中未選作最小生成樹的點的矩陣(也許不止一個)
  • j 確定已經選作最小生成樹的點的矩陣中的第一個點
  • k 確定未被選作最小生成樹的點的矩陣中的第一個點
技術分享圖片
clear;
clc;
n = 7;
a = [0 50 60 inf inf inf inf;
     0 0 inf 65 40 inf inf;
     0 0 0 52 inf inf 45;
     0 0 0 0 50 30 42;
     0 0 0 0 0 70 inf;
     0 0 0 0 0 0 inf;
     0 0 0 0 0 0 0];% 由於 a 是無向圖,航路票價沿著正對角線對稱,可以只寫出右上角
a = a + a;    % 由於票價沿正對角線對稱,即完整的 a 為 a + a 的轉置
result =[];   % 定義出 result
p =1;   % 當前只有第 1 個點為最小生成樹的節點
tb =2:n;   % 當前未作為最小生成樹的節點
while length(result) ~= n - 1   % 當生成樹的邊為 節點數-1 時,即最小生成樹生成(n個點 n-1 條邊)
    temp = a(p,tb);  % 存放當前最小生成樹連通的所有邊,用來求最短邊
    temp = temp(:);   % 將 temp 轉化成 1 列,讓求出的最短距離只有一個值
    d = min(temp);  % 求出最短距離
    [jb,kb] = find(a(p,tb)==d);  % 根據最短距離,找出哪些點符合最短距離的情況
    j = p(jb(1));    % 從當前最小生成樹中的點中
    k = tb(kb(1));   % 和當前未進入最小生成樹的點中挑出第一個點
    result = [result,[j;k;d]];   % 表示生成樹邊的起點、終點、權集合
    p = [p,k];   % 剛剛選的點進入最小生成樹
    tb(find(tb==k)) =[];    % 將進入最小生成樹的點剔除掉
end
result
prim 算法

技術分享圖片

最小生成樹問題之kruskal (待補充)

[matlab] 22.matlab圖論實例 最短路問題與最小生成樹 (轉載)