说明:
2024年11月6日更新代码
主要修改:
- 增加了对输入参数的判断
- 简化了部分变量的大小
- 明确了数据的使用范围
- 增加了对输入邻接矩阵的连通性判断
- 扩展节点遇到多个距离相同的节点时,只选择其中编号最小的节点
% 文件名:dijkstra.m
% 时间:2024年11月06日
% 来源:https://blog.csdn.net/lishan132/article/details/108527271
% 功能:利用dijkstra算法计算两点间的最短路径
% dist:起点与终点之间的最短距离值
% path:最短路径索引
% Dist:最短路径下的距离值
% A:邻接矩阵
% strat:起点编号
% dest:终点编号
%{
连通邻接矩阵测试数据
A = [0,12,inf,inf,inf,16,14;
12,0,10,inf,inf,7,inf;
inf,10,0,3,5,6,inf;
inf,inf,3,0,4,inf,inf;
inf,inf,5,4,0,2,8;
16,7,6,inf,2,0,9;
14,inf,inf,inf,8,9,0];
不连通邻接矩阵测试数据
A = [0,1,inf,inf,inf;
1,0,1,inf,inf;
inf,1,0,inf,inf;
inf,inf,inf,0,1;
inf,inf,inf,1,0];
start = 1;
dest = 4;
[dist, path, Distance] = dijkstra(A, start, dest);
%}
function [dist, path, Dist] = dijkstra(A, start, dest)
if size(A, 1) <= 1
error('邻接矩阵A至少需要两个节点构成');
end
if start == dest
error('起点和终点重合了');
end
if size(A, 1) ~= size(A, 2)
error('邻接矩阵A的行列数不一致');
end
if (start < 1 || start > size(A, 1))
error('起点start超出了节点范围');
end
if (start ~= round(start))
error('起点start不是整数');
end
if (dest < 1 || dest > size(A, 1))
error('终点dest超出了节点范围');
end
if (dest ~= round(dest))
error('终点dest不是整数');
end
for i = 1:size(A, 1)
for j = 1:size(A, 1) - i + 1
if A(i, j) < 0
error('邻接矩阵A中的权应该为非负值');
end
if A(i, j) ~= A(j, i)
error('邻接矩阵A不是对称矩阵');
end
end
end
m = (1);
n = 1:size(A, 1);
while size(m, 1) < size(A, 1)
idx = A(m(end), n) > 0 & A(m(end), n) < inf;
idx(1, m) = 0;
if sum(idx) > 0
m = [m, n(1, find(idx > 0, 1))];
else
warning('输入的邻接矩阵不连通,请确认以下两部分节点的连接情况\n')
disp(m)
disp(setdiff(n, m))
break
end
end
% 计算程序运行时间
tic %开始计时
% 初始化操作
p = size(A, 1); %计算顶点数目
S = (dest); %初始化集合S, 已加入到路径中的顶点编号
U = setdiff(1:p, S); %初始化集合U, 未加入到路径中的顶点编号
Dist(1, 1:p) = A(dest, 1:p); %初始化所有顶点到终点dest的距离
D(1, 1:p) = Dist(1, 1:p); %初始化所有顶点到当前顶点再到终点dest的距离
path(1, 1:p) = 0; %初始化最短路径节点连接记录表
path(1, D~=inf) = dest; %距离值不为无穷大时,将两顶点相连
% 寻找最短路径
while ~isempty(U) %判断U中元素是否为空
D(1, S) = inf; %忽略已处理顶点的距离值
if all(isinf(D))
break;
end
k = find(D(1:p) == min(D(1:p)), 1); %剩余顶点中距离终点最近的顶点编号
%更新顶点
S = [S, k]; %将顶点k添加到S中
U(U == k(1)) = []; %从U中删除顶点k
%计算距离
D(1, 1:p) = A(k, 1:p) + D(1, k); %先通过结点k,再到终点的距离值
D(1, 1:p) = min(D(1, 1:p), Dist(1, 1:p)); %取最小距离
%更新路径
path(1, D(1, 1:p) ~= Dist(1, 1:p)) = k; %更改连接关系,连接到结点k上
%更新距离
Dist(1, 1:p) = D(1, 1:p); %更新距离表为所有点到终点的最小值
end
dist = Dist(1, start); %取出指定起点到终点的距离值
toc %计时结束
% 输出结果
flag = 0;
fprintf('找到的最短路径为:')
while start ~= dest %到达终点时结束
next = path(1, start); %与当前点相连的下一顶点
if (next ~= 0)
fprintf('%d-->', start); %打印当前点编号
start = next; %更新当前点
else
flag = 1;
break;
end
end
if (flag ~= 0)
fprintf('没有找到想要的最短路径\n')
else
fprintf('%d\n', dest)
fprintf('最短路径对应的距离为:%d\n', dist)
end
前言
Dijkstra是一种用于计算最短路径的常用算法,由荷兰科学家Dijkstra在1956年提出
该算法主要适用于单源非负权边的无向图,其中:
(1)单源表示只有一个源节点,然后计算其它所有节点到该源节点的最短路径和距离
(2)非负权表示两个节点之间的权重是非负数
(3)无向表示节点之间没有方向的区别,从节点A到节点B与从节点B到A的权重值相同
求解示例
假如有A、