• MATLAB 单源最短路径Dijkstra)


    图的相关算法也算是自己的一个软肋了,当年没选修图论也是一大遗憾。

    图像处理中,也有使用图论算法作为基础的相关算法,比如图割,这个算法就需要求最大流、最小割。所以熟悉一下图论算法对于图像处理还是很有帮助的。

    Dijkstra和Bellman-Ford类似,都是解决单源最短路径问题,不同的是这个方法只能解决边为非负的问题,实现的好的Dijkstra算法运行时间要快于Bellman-ford。

    算法步骤如下:

    1.首先设置队列,所有节点入列,源节点值为0,其他节点值为无穷。

    2.然后在队列中找值最小的节点并出列。

    3.计算出列的节点所有后继节点的距离。

    4.松弛方法,如果新计算的距离小于上次计算的距离,那么更新距离,即将后继节点值设为较小的距离,并将后继节点的前趋设为当前的出列节点。

    5.对剩余的节点队列继续找最小值并出列,不断循环2、3、4步直到队列中没有节点了。

    步骤是上面没错,不过我程序中没有完全按照上述的步骤实现。不同的地方在于我没有做出列操作,而是通过标记节点的形式实现的。

    运行结果如下,图(是图不是图片)是算法导论367页上的:

    matlab代码如下,netplot和compresstable2matrix和上一篇使用的一样:

    main.m

     1 clear all;close all;clc
     2 %初始化邻接压缩表,1 2 10 表示从节点1到节点2,边的权重为10
     3 b=[1 2 10;1 4 5;2 3 1;
     4    2 4 2; 3 5 4;4 2 3;
     5    4 3 9; 4 5 2;5 1 7;
     6    5 3 6];
     7 
     8 m=max(max(b(:,1:2)));       %压缩表中最大值就是邻接矩阵的宽与高
     9 A=compresstable2matrix(b);  %从邻接压缩表构造图的矩阵表示
    10 netplot(A,1)                %形象表示
    11 
    12 S=inf(1,m);         %从开始的源点到每一个节点的距离
    13 S(1)=0;             %源点到自己的距离为0
    14 pa=zeros(1,m);      %存储每个节点的前驱,在松弛过程中赋值
    15 pa(1)=1;       %源点的前趋是自己 
    16 visit=zeros(1,m);   %标记某个节点是否访问过了
    17 index=1;            %从index节点开始搜索        
    18 
    19 %判断是否对所有节点都找的最短路径了。可能会有源点没有路径到目标节点的情况,那就无限循环了
    20 while sum(visit)~=m    %没有出队列操作,不过通过visit来等价的表示了
    21     
    22     visit(index)=1;                     %标记第index节点为已入列的节点
    23     [S pa]=relax(S,pa,A,visit,index,m);         %松弛,如果两个节点间有更短的距离,则用更短的距离
    24     index=extract_min(S,visit,index,m); %使用已访问的最小的节点作为下一次搜索的开始节点  
    25 
    26 end
    27 %最终我们需要的就是这两个值
    28 S       %源点到其他每一点的距离
    29 pa      %其他每一节点的前趋
    30 
    31 %算法到此结束,下面只是为了形象的表示而写的。
    32 re=[];
    33 for i=2:m
    34     re=[re;pa(i) i A(pa(i),i)];
    35 end
    36 A=compresstable2matrix(re);  %从邻接压缩表构造图的矩阵表示
    37 figure;
    38 netplot(A,1)                %形象表示

    relax.m

     1 %边缘松弛,使用更短的距离作为节点的值
     2 function [S pa]=relax(S,pa,A,visit,index,m)
     3    
     4    i=index;
     5    for j=1:m
     6         if A(i,j)~=inf && visit(j)~=1   %搜索没有标记过的节点
     7             if S(j)>S(i)+A(i,j)         %将较小的值赋给正在搜寻的节点
     8                 S(j)=S(i)+A(i,j);
     9                 pa(j)=i;
    10             end
    11         end        
    12     end    
    13 
    14 end

    extract_min.m

     1 %提取队列中尚未标记的最小的值的序号
     2 function index=extract_min(S,visit,index,m)
     3 
     4     Mi=inf;
     5     for j=1:m
     6         if visit(j)~=1
     7            if S(j)<Mi
     8                 Mi=S(j);
     9                 index=j;
    10            end
    11         end
    12     end    
    13 
    14 end
  • 相关阅读:
    redis 中 发布订阅 的 数据类型
    excelExport.js 导出 excel 表格
    Go 出现:err is shadowed during return(err在返回过程中被隐藏)
    Go 服务端 向 firebase Android 端 fcm 信息
    Python全栈day 03
    Python全栈day 01
    开发流程与版本管理规范
    php 魔术常量
    sql 消除重复
    重置mysql密码
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13646659.html
Copyright © 2020-2023  润新知