此为学习了数学建模清风老师课程后的学习笔记。
一、基础知识
1.1 floyd算法实现的目的
floyd算法是解决任意两点间的最短路径的一种算法,可以处理带负权重的有向图和无向图(但不可以存在负权回路)的最短路径问题。
1.2 算法特点
与迪杰斯特拉算法和贝尔曼福特算法相比,可以一次性给出任意两点之间的最短路径,而后两种算法一次只能给出给定的起点和重点的最短路径。
1.3 算法基本思想
i为起点,j为终点,Dmin(i,j)表示从i到j的最短路径的距离
若k位于i到j的最短路径之中,则有Dmin(i,j)= Dmin(i,k)+ Dmin(k,j)
若k不位于i到j的最短路径之中,则有Dmin(i,j)<Dmin(i,k)+ Dmin(k,j)
假如有八个样本点,现在要从点1走到点8,最短路径为1-->3-->4-->8。
如果某个节点(例如点3)位于起点1到终点8的最短路径上,用Dmin(i,j)表示从i到j的最短路径的距离,则有:
Dmin(1,8)= Dmin(1,3)+ Dmin(3,8)
如果某个节点(例如点5)不位于起点1到终点8的最短路径上,则有:
Dmin(1,8)< Dmin(1,5)+ Dmin(5,8)
1.4算法核心步骤
三层循环。这里理解为:由于要一次性给出任意两点之间的最短距离,假设有n个样本点,所以每一个样本点都要当一次起点 i 、终点 j 和中间点 k 。
二、代码部分
2.1 思路
2.1.1 定义函数
function[dist,path] = Floyd(D)
输入量:D:权重邻接矩阵(n*n)
输出量:dist:最短距离矩阵(n*n)
path:记录最短路径的矩阵(n*n)
2.1.2 初始化
初始化 dist,那么dist应该为最初任意两点间的距离构成的矩阵,即为D。
初始化 path,行代表起点,列代表终点,path(i,j)可以代表每一步的终点。
2.1.3 三次循环
进行三次循环,求出任意两点间的最短距离和路径。
2.2 代码
function[dist,path] = Floyd(D)
%%函数功能:实现Floyd算法
%输入量:D:权重邻接矩阵(n*n)
%输出量:dist:最短距离矩阵(n*n)
% path:记录最短路径的矩阵(n*n)
%%初始化
dist = D;
n = size(D,1);
path = zeros(n);
for j=1:n
path(:,j) = j; %初始路径都为起点到终点,第j列都为j
end
for i=1:n
path(i,i) = -1; %对角线的路径记为-1
end
%%三次循环
for k = 1:n
for i = 1:n
for j = 1:n
if dist(i,j) > dist(i,k) + dist(k,j)
dist(i,j) = dist(i,k) + dist(k,j);
path(i,j) = path(i,k); %这里不能写path(i,j)=k,因为path(i,k)也会随着循环更行
end
end
end
end
end
三、运行结果展示
3.1 举例
拿以下有向图做示范:
3.1.1 主代码部分
%将图转化成权重邻接矩阵
n = 5;
D = ones(n)./zeros(n); %初始化任意两点间的距离都为无穷
for i = 1:n
D(i,i) = 0; %对角线上的元素为0
end
%将图上的权重输入对应位置
D(1,2) = 3;
D(1,3) = 8;
D(1,5) = -4;
D(2,5) = 7;
D(2,4) = 1;
D(3,2) = 4;
D(4,3) = -5;
D(5,4) = 6;
D(4,1) = 2;
[dist,path] = Floyd(D);
disp('最短距离矩阵为:')
disp(dist)
disp('path矩阵为:')
disp(path)
3.1.2运行结果
3.1.3 如何看path矩阵
起点为3,终点为1的最短路径为:3-->2-->4-->1
把path矩阵的行1,2,3,4,5代表起点,列1,2,3,4,5代表终点,要从起点3到终点1,
先找到path(3,1) = 2,可以理解成从起点3走到了2,接下来要从2向1前进;
继续找到path(2,1)= 4,理解成从2走到了4,接下来从4向1前进;
找到path(4,1)= 1,意味着我们已经到达终点1。