matlab图论实例(一)最短路径问题——Floyd 和 dijkstra 算法

某公司在六个城市 c 1 , c 2 ,…., c 6 中有分公司,从 c i c j 的直接航程票价记在下述矩阵的 ( i , j ) 位置上。 ( 表示无直接航路),请帮助该公司设计一张城市 c 1 到其它城市间的票价便宜的路线图。

[ 0 50 40 25 10 50 0 15 20 25 15 0 10 20 40 20 10 0 10 25 25 20 10 0 55 10 25 25 55 0 ]

1. Floyd 算法

算法详解请戳

  • 变量解释:
    • 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

这里写图片描述

2. dijkstra 算法

算法详解请戳

  • 算法示意图:
    这里写图片描述

  • 变量解释:

    • n 是公司个数
    • m 存储票价
    • pb 存放标号信息,当 pb( i ) = 1,当前第 i 节点已标号,否则为 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

这里写图片描述

还有一个问题:
为啥 Floyd 和 dijkstra 求出来的 path 最下角不一样欸?

猜你喜欢

转载自blog.csdn.net/liyuanyue2017/article/details/82189301