代码改变世界

(原创)Dijkstra算法——方法(一)

2013-03-26 16:27  Keiven_LY  阅读(385)  评论(0编辑  收藏  举报
算法原理步骤如下:
1、初使时令 S={V0},T={其余顶点}T中顶点对应的距离值   
     若存在<V0,Vi>,d(V0,Vi)为<V0,Vi>弧上的权值   
     若不存在<V0,Vi>,d(V0,Vi)为 ∞   
2、从T中选取一个其距离值为最小的顶点W且不在S中,加入S    
3、对T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值比不加W的路径要短,则修改此距离值  
重复上述步骤2、3,直到S中包含所有顶点,即S=T为止 
 
说明:以下算法是给定起点与目的节点的最短路径
 
最短路函数部分:
 
function [l,t]=minPath(A,v)
  % 函数说明如下:
  % [l,t]=minPath(A,v)   Dijkstra算法
  % A为图中顶点的邻接矩阵,矩阵中的值表示两点之间的权值;
  % 如:A =
 
%        Inf       Inf       Inf    1.2000    9.2000       Inf    0.5000
%        Inf       Inf       Inf    5.0000       Inf    3.1000    2.0000
%        Inf       Inf       Inf       Inf       Inf    4.0000    1.5000
%     1.2000    5.0000       Inf       Inf    6.7000       Inf       Inf
%     9.2000       Inf       Inf    6.7000       Inf   15.6000       Inf
%        Inf    3.1000    4.0000       Inf   15.6000       Inf       Inf
%     0.5000    2.0000    1.5000       Inf       Inf       Inf       Inf
 
 %  v表示源节点(起始点)
 % l 存放源节点到其他各点的最短距离
 % t 存放当前节点的最短路径上的前一节点
    
  
n=length(A);%顶点个数
V=1:n;%顶点集合
s=v;%已经找到最短路的点集,初始为v,即源节点
l=A(v,:);%源节点到其他个点的初始距离,即为矩阵A中源节点所在行
t=v.*ones(1,n);%定义每一个节点的初始时的上一节点都为源节点
ss=setdiff(V,s); %setdif(A,B)函数功能是返回值为A中有,B中没有的值,且按升序排列返回。这里返回除源节点意外的所有节点的集合
nn=length(ss);%ss为还没有找到最短路的点集(即源节点以外的所有点的个数)
 
for j=1:n-1%一共进行n-1次循环(原因是去掉源节点)
    k=ss(1);
    for i=1:nn%对还没有找到最短路的点
       if l(k)>l(ss(i))
          k=ss(i);
          l(k)=l(ss(i));%在当前一行距离中取最小值
       end
    end
    if l(k)==inf%如果当前行最小值是无穷大,则结束
       break;
    else %否则k点的最短路找到
        s=union(s,k); %函数union(A, B) 返回矢量A与B的并集,A与B必须是数字,结果是排序的
        ss=setdiff(V,s);
        nn=length(ss);
    end
    if length(s)==n%全部点的最短路都找到
       break;
    else 
        for i=1:nn%以k为生长点,如果通过k点会更短,则更改当前最短距离
            if l(ss(i))>l(k)+A(k,ss(i))
               l(ss(i))=l(k)+A(k,ss(i));
               t(ss(i))=k;  
            end
        end
    end
end
 
主函数部分:
 
   clear;
   w=inf*ones(7);
   w(1,7)=0.5;w(1,4)=1.2;w(1,5)=9.2;
   w(2,7)=2;w(2,4)=5;w(2,6)=3.1;
   w(3,7)=1.5;w(3,6)=4;w(4,2)=5;
   w(4,1)=1.2;w(4,5)=6.7;
   w(5,1)=9.2; w(5,6)=15.6; w(5,4)=6.7;
   w(6,2)=3.1;w(6,3)=4;w(6,5)=15.6; 
   w(7,1)=0.5;w(7,2)=2;w(7,3)=1.5; 
   [l,t]=minPath(w,7)
  
   % 如果想更清楚的观看点v到点vv的最短距离与路径可用下面小程序:
    v=7;%注:这里的v要与上面的v一致(源节点)
    vv=4; % vv为目的节点
    k=vv;
    tt=vv;
    while(1)
      if k==v
         tt %若下面的tt=[tt,k],则路径为:vv <--...<-- v;若下面的 tt=[k,tt],则路径为v—>...—>vv
         l(vv) %距离
        break;
      else
         k=t(k);
         tt=[tt,k]; % 路径:目的节点——>源节点
         tt=[k,tt];  % 路径:源节点——>目的节点
      end
    end