目录
一、sparse创建稀疏矩阵
有如下无向图:
matlab代码:
clear all
clc
w=zeros(4); %返回一个4×4的零矩阵()中为标量。
w(1,2)=2;w(1,3)=3;w(1,4)=8;w(2,3)=6;w(2,4)=6; %w(起点,终点)=权重值
G=sparse(w) %将矩阵w转化为稀疏矩阵形式,矩阵w中任何0元素被去除,非零元素及其下标组成矩阵G。
运行后得到:
也可以用下面这个方法创建稀疏矩阵:
clear all
clc
%sparse([起点集合],[对应终点集合],[对应权重集合])
G=sparse([1 1 1 2 2],[2 3 4 3 4],[2 3 8 6 6]);
s=sparse(G)
同样,结果为:
二、有向图最短路径
例一、
使用函数:graphallshortestpaths,其语法为:
G:稀疏矩阵
0/false代表无向图,1/ture代表有向图。默认为true。
接下来我们要解决最短路径问题:
先创建一个有向图:
clear all
clc
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[41 99 51 32 15 45 38 32 36 29 21])
view(biograph(G,[],'ShowWeights','on'))
ShowWeights选项设置为on,图像里面会显示路径权值。并且用view函数将图片显示出来:
想求其中的最短路径使用graphallshortestpaths函数,只需要加一行代码::
clear all
clc
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[41 99 51 32 15 45 38 32 36 29 21])
view(biograph(G,[],'ShowWeights','on'))
graphallshortestpaths(G)
得到:
返回结果的含义:
以第一行为例,意思就是节点一分别到节点六的距离,那么第一个0就是节点一到节点一的距离。
因而很容易看出来,节点一到节点六的距离为95。
且通过图可以分析的路径为1 5 3 6
同理,节点二到节点一长度为111的路径为2-3-4-1.
例二、
上种方法需要我们自己去判断最短路径的途径,有没有什么方法能够让我们省区判断呢?
看下面这种方法:
此类方法看路径不太容易懂,可以不必纠结怎么来的,会用即可,本人认为可能是一一做比的一个过程。
保存该函数dijkstra.m
function [min,path]=dijkstra(w,start,terminal)
n=size(w,1); label(start)=0; f(start)=start;
for i=1:n
if i~=start
label(i)=inf;
end, end
s(1)=start; u=start;
while length(s)<n
for i=1:n
ins=0;
for j=1:length(s)
if i==s(j)
ins=1;
end
end
if ins==0
v=i;
if label(v)>(label(u)+w(u,v))
label(v)=(label(u)+w(u,v));
f(v)=u;
end
end
end
v1=0;
k=inf;
for i=1:n
ins=0;
for j=1:length(s)
if i==s(j)
ins=1;
end
end
if ins==0
v=i;
if k>label(v)
k=label(v); v1=v;
end
end
end
s(length(s)+1)=v1;
u=v1;
end
min=label(terminal); path(1)=terminal;
i=1;
while path(i)~=start
path(i+1)=f(path(i));
i=i+1 ;
end
path(i)=start;
L=length(path);
path=path(L:-1:1);
这回再来解决上面的问题:(方便观看,复制一张过来)
这回的代码为:
% 构造邻接矩阵
a = zeros(6);
a = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[41 99 51 32 15 45 38 32 36 29 21])
a(a==0) = inf; % 零元素换成inf
a(eye(6,6)==1)=0; % 对角线换成 0。eye()返回6×6的单位矩阵。无参数时表示标量1。
view(biograph(a,[],'ShowWeights','on'))
[min,path]=dijkstra(a,1,6) % dijkstra模型求解节点一到节点六最短路径(单源点)
运行后:
运行后:
得出最短路径长95,路径过程1 5 4 6
三、无向量最短路径
例一、
求解此无向量最短路径:
先使用第一种方式解决:
clear all
clc
W = [41 99 51 32 15 45 38 32 36 29 21];
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],W)
UG = tril(G + G')
view(biograph(UG,[],'ShowArrows','off','ShowWeights','on'))
得到稀疏矩阵:
添加一行代码:
clear all
clc
W = [41 99 51 32 15 45 38 32 36 29 21];
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],W);
UG = tril(G + G')
view(biograph(UG,[],'ShowArrows','off','ShowWeights','on'))
graphallshortestpaths(UG,'directed',false)
可以看出节点一到节点六最短距离为82,路径为1 5 3 6
例二、
使用shortestpath求解更加方便,代码如下:
clc
clear all
% 构造邻接矩阵
G = zeros(6);
G = graph([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[41 99 51 32 15 45 38 32 36 29 21])
plot(G,'EdgeLabel',G.Edges.Weight)
[P,d] = shortestpath(G,1,6)
得出:
使得解决问题的效率加快了。
当然,不是只有无向量的可以用,有向量的也可以,回到有向量的看一眼:
clear all
clc
G = digraph([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[41 99 51 32 15 45 38 32 36 29 21])
plot(G,'EdgeLabel',G.Edges.Weight)
[path,min]=shortestpath(G,1,6)
结果:
【这里借用一个大佬的话,有向量和无向量的差别在于无向量比有向量多验证了一次节点反过来的情况】
四、感悟
求最短路径的方式不只这几种,不过可以先掌握这几种。
本次知识大概明白,但发现许多小的知识点需要补充和日后的积累。
【此篇为川川博主的打卡,学习笔记。】