最短路径问题笔记----Dijkstra和Floyd(Matlab实现)

Floyd

基本思路就是对于任意两个节点,看看这两个点是直接连接近,还是由起点经过一个除这两个节点之外的中转点再到终点近
下面函数是由邻接矩阵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

上述的函数会得到两个矩阵,下面举例看看如何通过矩阵找到各个最短路径
最短路径问题笔记----Dijkstra和Floyd(Matlab实现)_第1张图片
这里有六个节点
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

Dijkstra

固定起点的最短路,是一条路径(顶点与边均不重复的通路),又因为最短路的任一段也是最短路。
所以可以采用树的生长过程求从起点到其余顶点的最短路。

首先规定下:
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------具有永久标号的顶点集

最短路径问题笔记----Dijkstra和Floyd(Matlab实现)_第2张图片

举例:下面是个邻接矩阵
最短路径问题笔记----Dijkstra和Floyd(Matlab实现)_第3张图片
最短路径问题笔记----Dijkstra和Floyd(Matlab实现)_第4张图片

代码实现

下面函数是求从固定起点到其他所有点的最短路

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);

你可能感兴趣的:(图论,matlab,算法,数学建模)