用matlab实现Dijkstra算法(最短路问题)
首先本文设计了两种输入方式,可直接输入连接节点构成的矩阵,W(i,j)表示从i点到j点的路径权重;也可以输入各节点的子节点及对应权重,采用元胞结构,可以更方便输入。
注意在使用时注释掉另一种输入方式
这是运行结果:
另外在这里也简单将从初始点到目标点的最短路径输出了一下
clc;
clear;
%输入节点个数
n=9;
%输入目标终点的下标
m=8;
%到目标终点的反向路径
path=zeros(1,n);
path(1)=m;
%***********************************************************************************************
%直接输入有向图或无向图W
% W=[0 6 3 1 inf inf inf inf inf;inf 0 inf inf 1 inf inf inf inf;inf 2 0 2 inf inf inf inf inf;
% inf inf inf 0 inf 10 inf inf inf;inf inf inf 6 0 4 3 6 inf;inf inf inf inf 10 0 2 inf inf;
% inf inf inf inf inf inf 0 4 inf;inf inf inf inf inf inf inf 0 inf;inf inf inf inf 2 inf inf 3 0];
% W=[0 6 3 1 inf inf inf inf inf;6 0 2 inf 1 inf inf inf inf;3 2 0 2 inf inf inf inf inf;
% 1 inf 2 0 6 10 inf inf inf;inf 1 inf 6 0 4 3 6 2;inf inf inf 10 4 0 2 inf inf;
% inf inf inf inf 3 2 0 4 inf;inf inf inf inf 6 inf 4 0 3;inf inf inf inf 2 inf inf 3 0];
% W=[0 2 inf 8 inf inf inf inf inf inf inf;inf 0 inf 6 1 inf inf inf inf inf inf;
% 1 inf 0 inf inf inf 9 inf inf inf inf;inf inf 7 0 inf inf inf inf inf inf inf;
% inf inf inf 5 0 inf inf inf 1 inf inf;inf inf inf 1 3 0 4 inf inf inf inf;
% inf inf inf 2 inf inf 0 inf 3 1 inf;inf inf inf inf 2 inf inf 0 inf inf 9;
% inf inf inf inf inf 6 inf 7 0 inf inf;inf inf inf inf inf inf inf inf 1 0 4;
% inf inf inf inf inf inf inf inf 2 inf 0];
%***********************************************************************************************
%通过输入子节点下标与权值产生矩阵W
V{1,1}=[2 3 4;6 3 1];V{1,2}=[5;1];V{1,3}=[2 4;2 2];V{1,4}=[6;10];V{1,5}=[4 6 7 8;6 4 3 6];
V{1,6}=[5 7;10 2];V{1,7}=[8;4];V{1,8}=[];V{1,9}=[5 8;2 3];
W=zeros(n);
for i=1:n %生成对角线元素为零,其他元素为inf的初始W矩阵
for j=i:n
if (i==j)
continue;
end
W(i,j)=inf;
end
end
for i=1:n %通过输入的子节点下标与权值产生最终W矩阵
if (size(V{1,i})==0)
continue;
end
for j=1:size(V{1,i},2)
W(i,V{1,i}(1,j))=V{1,i}(2,j);
end
end
%**********************************************************************************************
%定义已是P标号节点的集合S;P向量与T向量存v1到各点的权值;La向量存各节点的父节点下标
S=zeros(1,n);P=S;
for i=2:n
P(i)=inf;
end
S(1)=1;T=P;La=P;
k=1; %最新P节点下标
while(1) %最外层循环,不断循环Dijkstra算法的二三步
for i=1:n %第二步
if (W(k,i)~=0 && W(k,i)~=inf && S(i)~=1) %满足此条件允许更新权值
if(P(k)+W(k,i)<T(i))
T(i)=P(k)+W(k,i); %更新第i节点的T值
La(i)=k; %更新第i节点的父节点下标
end
end
end
for i=1:n %将T中已经存在P中的对应权值变成无穷,取最小T时不参与运算
if (S(i)~=0)
T(i)=inf;
end
end
[TW,k]=min(T); %找到当前T标号中最小权值与下标,进行第三步
if(TW==inf) %循环终止条件
break;
end
P(k)=TW; %更新P节点下标及权重
S(k)=1; %更新P标号节点的集合
end
%输出第一点到目标终点的最短路径
i=1;
while(m~=0)
i=i+1;
path(i)=La(m);
m=La(m);
end
fprintf('从V1到V%d的最短路径为:\n',path(1));
while(1)
fprintf('V%d',path(i-1));
i=i-1;
if(i==1) %循环终止条件
fprintf('\n');
break;
end
fprintf('->');
end