基本思路就是对于任意两个节点,看看这两个点是直接连接近,还是由起点经过一个除这两个节点之外的中转点再到终点近
下面函数是由邻接矩阵A得到两点之间的最短距离矩阵和路径矩阵(两个点之间的中间节点值)
function [minA,B]=minpath(A)
n=size(A,1); //计算出邻接矩阵的行号或列号n
B=zeros(n); //创建一个与A同大小的矩阵,该矩阵代表两个点最短路径上的中间经过的节点
for i=1:n //对B初始的化
for j=1:n
B(i,j)=j;
end
end
for k=1:n //Floyd实现 ,相当于用每一个节点去试所有的一对节点
for i=1:n //看看是原本的这一对节点直接距离近还是经过特定节点(k)的距离近
for j=1:n //那个近取那个,再对A和B矩阵的元素更改
if A(i,j)>A(i,k)+A(k,j)
A(i,j)=A(i,k)+A(k,j);
B(i,j)=B(i,k);
end
end
end
end
minA=A;
end
上述的函数会得到两个矩阵,下面举例看看如何通过矩阵找到各个最短路径
这里有六个节点
minA表明了任意两点最短距离:如第一个节点与第二,三,四,五,六个节点最小距离分别为35,45,35,25,10
B表明了任意两点之间最短路线需要经过的节点:如第一个节点到第四个节点,看B矩阵的第一行第四列(或者第四行第一列)值为5,可知需要途径第五个节点,以此类推。
如果要写一个返回两点之间距离最短及路线的函数
function [mindistance,path]=minpath(A,b,e) // b为起点,e为终点
n=size(A,1); //计算出邻接矩阵的行号或列号n
B=zeros(n); //创建一个与A同大小的矩阵,该矩阵代表两个点最短路径上的中间经过的节点
for i=1:n //对B初始的化
for j=1:n
B(i,j)=j;
end
end
for k=1:n //Floyd实现
for i=1:n
for j=1:n
if A(i,j)>A(i,k)+A(k,j)
A(i,j)=A(i,k)+A(k,j);
B(i,j)=B(i,k);
end
end
end
end
mindistance=A(b,e);
path=b;
t=b;
while t~=e
temp=B(t,e);
path=[path,temp];
t=temp;
end
固定起点的最短路,是一条路径(顶点与边均不重复的通路),又因为最短路的任一段也是最短路。
所以可以采用树的生长过程求从起点到其余顶点的最短路。
首先规定下:
l(v)-------从起点 u 0 u_0 u0到顶点 v v v的一条线的距离,与自身是0,两点间无线为inf(无穷大)
z(v)------ v v v的父母结点,即 v v v的前一个结点。在固定起点的最短路图(树状)中,z(v)结点的 下一个(子节点) 为 v v v
w(u,v)----u和v两个顶点的一条线的距离
S------具有永久标号的顶点集
下面函数是求从固定起点到其他所有点的最短路
function [l,z]=tree(A,m) //A为邻接矩阵,m为固定起始顶点的序号
n=size(w,1); //一共有n个顶点
A1=A(m,:); //先找初始顶点距离其他顶点的一条线距离,自身是0,没有一条线为inf(无穷大)
for i=1:n //初始化
l(i)=A1(i); //顶点距离起点的距离
z(i)=m; //l(i)中,i顶点的前一个顶点
end
s=[]; //标号的点集
s(1)=m;
u=s(1);
for k=1:n-1 //不断更新l(v)和z(v)
for i=1:n
for j=1:k
if i~=s(j)
if l(i)>l(u)+A(u,i)
l(i)=l(u)+A(u,i);
z(i)=u;
end
end
end
end
ll=l; //对更改完的l(v)的元素作比较,找出最小的点划入s集内
for i=1:n
for j=1:k
if i~=s(j)
ll(i)=ll(i);
else
ll(i)=inf; //对于已经在s集内的点设为无穷大,方便找到最小的
end
end
end
lv=inf;
for i=1:n //开始比较
if ll(i)<lv
lv=ll(i);
v=i;
end
end
s(k+1)=v;
u=s(k);
end
end
下面函数为两点之间的最短路径
function [mindistance,path]= func(A,s,e)
n=size(A,1);
visited(1:n)=0; //标记数组,顶点被标记为1时表示在S集内,标记为0表示不再。
l(1:n)=inf;
l(s)=0;
z(1:n)=0;
for i=1:n-1
temp=l;
id1=find(visited==1);
temp(id1)=inf; //将已经在S集内的点设为无穷大,用于比较大小
[t,u]=min(temp); //找到最小值点设为u
visited(u)=1;
id2=find(visited==0);
for v=id2
if l(v)>l(u)+A(u,v)
l(v)=l(u)+A(u,v);
z(v)=u;
end
end
end
path=[];
if z(e)~=0
t=e;
path=[e];
while t~=s
p=z(t);
path=[p path];
t=p;
end
end
mindistance=l(e);