本文代码无说明均为 m a t l a b matlab matlab
clear;clc;
a=zeros(6);
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;
a(2,3)=15;a(2,4)=20;a(2,6)=25;
a(3,4)=10;a(3,5)=20;
a(4,5)=10;a(4,6)=25;
a(5,6)=55;
a=a+a';
a(find(a==0))=inf;%所有不存在的边置为正无穷
vis(1:length(a))=0;%初始化标记数组
dis(1:length(a))=inf;
dis(1)=0;
while sum(vis)<length(a)
to=find(vis==0);%to是未访问过的节点数组
minpos=find(dis(to)==min(dis(to)));
%找到to中dis最小的节点在to中的位置
now=to(minpos(1));%多个节点dis相同,取一个即可
vis(now)=1;%标记
dis(to)=min(dis(to),dis(now)+a(now,to));
%这样写就可以更新to中所有节点的dis
end
dis
code:
function [Mindis,path]=dijkstra(a,st,ed)
% 输入:邻接矩阵a(i,j)是指i到j之间的距离,可以是有向的
% st—起点的标号, ed—终点的标号
% 输出:distance—最短路的距离, path—最短路的路径
n=size(a,1);
visited(1:n) = 0; %初始化标记数组
distance(1:n) = inf; % 保存起点到各顶点的最短距离
distance(st) = 0;
parent(1:n) = 0;%存节点i的上一个节点
for i = 1: n-1
temp=distance;
id1=find(visited==1); %查找已经标记的点
temp(id1)=inf; %已标号点的距离换成无穷
[Min, now] = min(temp); %找标号值最小的顶点
visited(now) = 1; %标记已经标记的顶点
id2=find(visited==0); %查找未标记的顶点
for to = id2 %更新最短路
if a(now, to) + distance(now) < distance(to)
distance(to) = distance(now) + a(now, to);
parent(to) = now;
end
end
end
path = [];
if parent(ed) ~= 0 % ~=是不等于,这句话表示st到ed的最短路存在
pos = ed; path = [ed];
while pos ~= st
p = parent(pos);
path = [p path];%因为是倒着找的,所以把p和之前的path拼接起来
pos = p;
end
end
Mindis = distance(ed);
code:
function [dist,path]=floyd(a,st,ed)
% 输入:a—邻接矩阵a(i,j)是指 i 到 j 之间的距离,可以是有向的
% st—起点的标号;ed—终点的标号
% 输出:dist—最短路的距离;% path—最短路的路径
n=size(a,1); path=zeros(n);
for i=1:n
for j=1:n
if a(i,j)~=inf
path(i,j)=j; %j 是 i 的后续点
end
end
end
for k=1:n
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);
path(i,j)=path(i,k);
end
end
end
end
dist=a(st,ed);
path=st; t=st;
while t~=ed
temp=path(t,ed);
path=[path,temp];
t=temp;
end
参数矩阵 a a a 的初始化
a=zeros(7);%首先置为方阵
a(1,2)=50; a(1,3)=60; a(2,4)=65; a(2,5)=40;
a(3,4)=52;a(3,7)=45; a(4,5)=50; a(4,6)=30;
a(4,7)=42; a(5,6)=70; %赋值上三角
a=a+a';%填充下三角
a(find(a==0))=inf;%不存在的边置为正无穷
code:
function result=prim(a)
%输入:邻接矩阵a(i,j)是指i到j之间的距离
%输出:result的第一、二、三行分别表示生成树边的起点、终点、权集合
%相当于一列存的是一条边
result=[];
pos=1;
n=length(a);
tb=2:n;
for i=1:n-1 %循环n-1次
temp=a(pos,tb);
temp=temp(:);
d=min(temp);
[jb,kb]=find(a(pos,tb)==d);
j=pos(jb(1));
k=tb(kb(1));
result=[result,[j;k;d]];pos=[pos,k];tb(find(tb==k))=[];
end
矩阵初始化,只需要赋值上三角即可
a(1,2)=50; a(1,3)=60; a(2,4)=65; a(2,5)=40;
a(3,4)=52;a(3,7)=45; a(4,5)=50; a(4,6)=30;
a(4,7)=42; a(5,6)=70;
code:
function result=kruskal(a)
%输入:%输入:邻接矩阵a(i,j)是指i到j之间的距离
%输出:result的第一、二、三行分别表示生成树边的起点、终点、权集合
%相当于一列存的是一条边
[i,j,b]=find(a);
data=[i';j';b'];index=data(1:2,:);
loop=max(size(a))-1;
result=[];
while length(result)<loop
temp=min(data(3,:));
flag=find(data(3,:)==temp);
flag=flag(1);
v1=index(1,flag);v2=index(2,flag);
if v1~=v2
result=[result,data(:,flag)];
end
index(find(index==v2))=v1;
data(:,flag)=[];
index(:,flag)=[];
end
一名推销员准备前往若干城市推销产品,然后回到他的出发地。如何为他设计一条最短的旅行路线(从驻地出发,经过每个城市恰好一次,最后返回驻地)
一个可行的办法是首先求一个 H a m i l t o n Hamilton Hamilton 圈 C C C ,然后适当修改 C C C 以得到具有较小权的另一个 H a m i l t o n Hamilton Hamilton 圈。修改的方法叫做改良圈算法。
主函数
clear;clc;
a=zeros(6);
a(1,2)=56;a(1,3)=35;a(1,4)=21;a(1,5)=51;a(1,6)=60;
a(2,3)=21;a(2,4)=57;a(2,5)=78;a(2,6)=70;
a(3,4)=36;a(3,5)=68;a(3,6)=68; a(4,5)=51;a(4,6)=61;
a(5,6)=13;
a=a+a';
a(find(a==0))=inf;
c1=[5 1:4 6];
[circle,long]=modifycircle(a,c1);
c2=[5 6 1:4];%改变初始圈,起点不动
[circle2,long2]=modifycircle(a,c2);
if long2<long
long=long2;
circle=circle2;
end
circle,long
%*******************************************
%修改圈的子函数
%*******************************************
function [circle,long]=modifycircle(a,c1)
%输入:初始邻接矩阵a,初始圈c1,
%输出:路径轨迹circle,最小长度long
L=length(a);
flag=1;
while flag>0
flag=0;
for i=1:L-3
for j=i+2:L-1
if a(c1(i),c1(j))+a(c1(i+1),c1(j+1))<...
a(c1(i),c1(i+1))+a(c1(j),c1(j+1))
flag=1;
c1(i+1:j)=c1(j:-1:i+1);
end
end
end
end
long=a(c1(1),c1(L));
for i=1:L-1
long=long+a(c1(i),c1(i+1));
end
circle=c1;