(原创)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