学习笔记:Dijkstra算法

一、算法介绍

迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家迪杰斯特拉于1959年题出。是从一个节点遍历其余各节点的最短路径算法,解决的是有权图中最短路径问题。

二、算法思想

1、设G=(V,E)是一个带权有向图,把图中节点集合V分成两组,第一组为已求出最短路径的节点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径,就将该节点加入到集合S中,直到全部节点都加入到S中,算法就结束了);

2、第二组为其余未确定最短路径的节点集合(用U表示),按最短路径长度的递增次序依次把第二组的节点加入S中。在加入的过程中,总保持从源点v到S中各节点的最短路径长度不大于从源点v到U中任何节点的最短路径长度。
3、此外,每个节点对应一个距离,S中的节点的距离就是从v到此节点的最短路径长度,U中的节点的距离,是从v到此节点只包括S中的节点为中间节点的当前最短路径长度。

三、算法运作流程

3.1准备过程

         此算法选用单向有权图,可以找到每个节点的临近节点表,因matlab用数字遍历更为方便,所以将A-G的字母节点改为1-7数字节点。

3.2算法初始化

1、初始时,S只包含起点s;U包含除s外的其他节点,且U中节点的距离为"起点s到该节点的距离"[例如,U中节点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
2、从U中选出"距离最短的节点k",并将节点k加入到S中;同时,从U中移除节点k。
3、更新U中各个节点到起点s的距离。之所以更新U中节点的距离,是由于上一步中确定了k是求出最短路径的节点,从而可以利用k来更新其它节点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。重复步骤(2)和(3),直到遍历完所有节点。

3.3算法过程

1、假如起点为D,终点为A,选取节点D,S={D(0)}  U={A(∞),B(∞),C(3),E(4),F(∞),G(∞)}

2、根据上一轮的U选取节点C,S={D(0),C(3)} 

D经过CB:最短为DC+CB=10+3=13,小于第一步B点的无穷,所以需要更新

D经过CE:最短为DC+CE=3+5=8,大于第一步E点的4,所以不需要更新

D经过CF:最短为DC+CF=3+6=9,小于第一步F点的无穷,所以需要更新

U={A(∞),B(13),E(4),F(9),G(∞)}

 3、根据上一轮的U选取节点E,S={D(0),C(3),E(4)} 

D经过EB:与E点不相邻,所以不需要更新

D经过EF:最短为DE+EF=4+2=6小于第二步F的9,所以需要更新

D经过EG:最短为DE+DG=4+8=12小于第二步G的无穷,所以需要更新

U={A(∞),B(13),F(6),G(12)}

4、根据上一轮的U选取节点F, S={D(0),C(3),E(4),F(6)} 

D经过FA:最短为DE+DF+FA=4+2+16=22,小于第三步A的无穷,所以需要更新

D经过FB:最短为DE+EF+FB=4+2+7=13,等于第三步B的13,所以不需要更新

D经过FG:最短为DE+EF+FG=4+2+9=15,大于第三步G的12,所以不需要更新

U={A(22),B(13),G(12)}

5、根据上一轮的U选取节点G, S={D(0),C(3),E(4),F(6),G(12)} 

D经过GA:最短为DE+EG+GA=4+8+14=26,大于第四步A的22,所以不需要更新

U={A(22),B(13)}

6、根据上一轮的U选取节点B,S={D(0),C(3),E(4),F(6),G(12),B(13)

D经过BA:DC+CB+BA=3+10+12=25大于第五步A的22,所以不需要更新

U={A(22)}

7、将A放入S中,S={D(0),C(3),E(4),F(6),G(12),B(13),A(22)}   U={Ø}

8、即D到A的最优路径为D→E→F→A,最短距离22。

% Dijkstra算法
% 作者:Ally
% 日期:2020/12/18

clc
clear
close all

%% 图定义
% 根据节点的邻近节点表及字母节点-数字节点对应表,构造节点元胞数组
nodes_dist = cell(0);
nodes_dist(1,:) = {1, [2, 6, 7], [12, 16, 14]};
nodes_dist(2,:) = {2, [1, 3, 6], [12, 10, 7]};
nodes_dist(3,:) = {3, [2, 4, 5, 6], [10, 3, 5, 6]};
nodes_dist(4,:) = {4, [3, 5], [3, 4]};
nodes_dist(5,:) = {5, [3, 4, 6, 7], [5, 4, 2, 8]};
nodes_dist(6,:) = {6, [1, 2, 3, 5, 7], [16, 7, 6, 2, 9]};
nodes_dist(7,:) = {7, [1, 5, 6], [14, 8, 9]};

%% 算法初始化
% S/U的第一列表示节点编号
% 对于S,第二列表示从源节点到本节点已求得的最小距离,不再变更;
% 对于U,第二列表示从源节点到本节点暂时求得的最小距离,可能会变更
S = [4, 0];
U(:,1) = [1, 2, 3, 5, 6, 7];
U(:,2) = [inf, inf, 3, 4, inf, inf];

% 最优路径及暂时最优路径的初始化
path_opt = cell(7,2);
path_opt(4,:) = {4, 4};

path_temp = cell(7,2);
path_temp(3,:) = {3, [4, 3]};
path_temp(4,:) = {4, 4};
path_temp(5,:) = {5, [4, 5]};

%% 循环遍历所有节点
while ~isempty(U)
    
    % 在U集合找出当前最小距离值及对应节点,并移除该节点至S集合中
    [dist_min, idx] = min(U(:,2));
    node_min = U(idx, 1);
    S(end+1,:) = [node_min, dist_min];
    U(idx,:) = [];
    
    % 将最小距离值的节点添加到最优路径集合
    path_opt(node_min,:) = path_temp(node_min,:);
    
    %% 依次遍历最小距离节点的邻节点,判断是否在U集合中更新邻节点的距离值
    for i = 1:length(nodes_dist{node_min, 2})
        
        % 需要判断的节点
        node_temp = nodes_dist{node_min, 2}(i);
        
        % 找出U集合中节点node_temp的索引值
        idx_temp = find(node_temp == U(:,1));
        
        % 判断是否更新
        if ~isempty(idx_temp)
            if dist_min + nodes_dist{node_min, 3}(i) < U(idx_temp, 2)
                U(idx_temp, 2) = dist_min + nodes_dist{node_min, 3}(i);
                
                % 更新暂时最优路径
                path_temp{node_temp, 1} = node_temp;
                path_temp{node_temp, 2} = [path_opt{node_min, 2}, node_temp];                
            end
        end
    end
end
        

学习自B站:小黎的Ally

视频链接:路径规划与轨迹跟踪系列算法学习_第1讲_Dijkstra算法_哔哩哔哩_bilibili

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值