MATLAB实现Dijkstra算法教程‌

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。

它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

算法思想 每次找到离源点最近的一个顶点,然后以该顶点为中心,然后得到源点到其他顶点的最短路径。

迪杰斯特拉算法:

    设G为赋权有向或无向图,G边上的权非负。求G中从顶点u_{0} 到其余顶点的最短路。

    S:具有永久标号的顶点集.

    对每个顶点,定义两个标记(l(v),z(v)),其中:

    l(v):表示从顶点u_{0} v的一条路的权.

    z(v)v的父亲点,用以确定最短路的路线.

    算法的过程就是在每一步改进这两个标记,使最终l(v)为从顶点u_{0} v的最短路的权.输入为带权邻接矩阵W.

    (1)赋初值:令S=\left\{ u_{0}  \right\} ,l(u_{0} )=0,\forall v\in \bar{S} =V左除S

                            令l(v)=W(u_{0},v),z(v)=u_{0},u\leftarrow u_{0}.

    (2)更新l(v),z(v):\forall v\in \bar{S}=V左除S,若l(v)>l(u)+W(u,v),

                                         则令l(v)=l(u)+W(u,v),z(v)=u

    (3)设v^* 是使l(v)取最小值的\bar{S}中的的顶点,则令S=S\cup  \left\{ v^* \right\} ,u\leftarrow v^*.

    (4)若\bar{S}\neq  空集,则转(2);否则,停止.

       用上述算法求出的l(v)就是u_{0}到v的最短路的权,从v的父亲点标记z(v)追溯到 u_{0},就得到u_{0}到v的最短路的路线.

实现:MATLAB

函数:

% 功能:     实现改良的Dijkstra算法
% 修改时间:  初版2021-8-30 20:00,修改于2022-10-25 22:35
% 编写人:   湖北工业大学.机械工程学院.力创团队.人工智能部.黄沛鑫
% 版权声明:  如需转载,请务必标明出处
function op=dijkstra2(W,startsite,pausesite)
    % 说明:
    %     1. 函数输出为行向量op,op记录着两个目标点的最短路径
    %     2. 函数名为dijkstra2
    %     3. 函数输入变量有三个。W是赋权图的邻接矩阵,startsite是起点,pausesite是终点;
    % step1:读取邻接矩阵的大小
        [m1,~] = size(W); % 邻接矩阵是方阵,所以大小是m1*m1的矩阵
    % step2: 如果起始点不是邻接矩阵的首个点,需要将邻接矩阵转变一下
        if startsite ~= 1 %%%
            W([1 startsite],:) = W([startsite 1],:); % 交换行
            W(:,[1 startsite]) = W(:,[startsite 1]); % 交换列
        end
    % step3: 初始化
        s = zeros(1, m1);               % s向量 用来储存起点到各个点的最短路径的值
        fathersite = zeros(1, m1);      % fathersite向量 用来储存对应点的父点
                                        % 注:父点解释
                                        %    假设从1号点到6号点的路径为1->3->5->7->6
                                        %    那么 6 的父点是 7,7的父点是5.
                                        %    这里使用父点这个概念,用以帮助路径的表达
        t = zeros(1, m1);               % t向量 用来储存起点到各个点的可能的最短路径的值
        for i = 1:m1
            t(i) = nan;                 % 将t中元素的值进行处理,方便后面进行工作。后面将会在t中,挑出某一次迭代中,路径值最小的点,然后再进行处理。
        end
        num = 1:m1;                     % num向量 是一个从1到m1,步进为1的向量。用来记录对应点是否已经找到最短路径。若是找到了,那么后面将会对应作出处理
        newsite = 1;                    % newsite是用来记录最新的,已经被确认下来的,找到到起点的最短路径的解的点
    % step4: 主要迭代
        s (1) = 0;                      % 将起点到起点的距离设置为0
        for i=1:1:10000000000000000     % 这个循环通过迭代不断更新数据
            for j = num                 % 历遍
                if j == 0               % 必要性判断
                    continue
                end
                if W(newsite, j) ~= inf
                    c = W (newsite, j)+s (newsite);
                    if isnan (t(j)) || c < t(j)
                        t(j) = c;
                        fathersite(j)= newsite;
                    end
                end
            end
            newsite = find (t == min (t));
            s (newsite) = min (t);
            num (newsite) = 0;           % 与必要性判断呼应
            t (newsite) = nan;
            if sum(num)==0
                break;
            end                 % 如果所有的t全是nan值的话,意味着最短路径已经找到,停止迭代。
        end
    % step5: 进行step2的逆变换
        for i=1:m1 % 将起点的值换为编号,将一号点的值换为编号
            if fathersite(i)==1
                fathersite(i)=startsite;
            elseif fathersite(i)==startsite
                fathersite(i)=1;
            else
                HBUThpx=0; % 无用步骤
            end
        end
        io=fathersite(1);
        fathersite(1)=fathersite(startsite);
        fathersite(startsite)=io;%这里我们将结果中的起点和1号点换个位置。因为一开始,我们将邻接矩阵的第一列和第一行换成了起点
        po=fathersite(pausesite);
        op=[po,pausesite];
        for i=1:m1 % 历遍,更新储存路径值
            if po~=1
                po=fathersite(po);% 通过每个点的父点溯回路径
                op=[po,op];
            else
                break;%当路径点寻找到了1号点,结束循环
            end
        end
    % step6: 结果优化
        line=[];
        for i=1:length(op)
            if i==1
                line=[line,op(i)];
            else
                if op(i)==op(i-1)
                    continue;
                end
                line=[line,op(i)];
            end
        end
        op=line;
end

测试:

%测试数据
clc;clear;
weight1=[0   2   1   8   inf inf inf inf
        2   0   inf 6   1   inf inf inf
        1   inf 0   7   inf inf 9   inf
        8   6   7   0   5   1   2   inf
        inf 1   inf 5   0   3   inf 9
        inf inf inf 1   3   0   4   6
        inf inf 9   2   inf 4   0   3
        inf inf inf inf 9   6   3   0];
startsite1=1;
pausesite1=5;
op1=dijkstra2(weight1,startsite1,pausesite1);
disp([num2str(startsite1),'号点到',num2str(pausesite1),'号点的路径是',num2str(op1)]);
%
weight2=[0  1   12  inf inf inf
        inf 0   9   3   inf inf
        inf inf 0   inf 5   inf
        inf inf 4   0   13  15
        inf inf inf inf 0   4
        inf inf inf inf inf 0];
startsite2=2;
pausesite2=6;
op2=dijkstra2(weight2,startsite2,pausesite2);
disp([num2str(startsite2),'号点到',num2str(pausesite2),'号点的路径是',num2str(op2)]);

结果:

1号点到5号点的路径是1  2  5
2号点到6号点的路径是2  4  3  5  6

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空