• 单源最短路径-Dijkstra算法


    1.算法标签

    贪心

    2.算法描述

    具体的算法描述网上有好多,我觉得莫过于直接wiki,只说明一些我之前比较迷惑的。

    对于Dijkstra算法,最重要的是维护以下几个数据结构:

    • 顶点集合S : 表示已经找出从源点出发最短路径的顶点集合
    • 顶点集合Q: S在所有顶点集合中的补集,即V-S
    • 距离数组dist : 在程序执行过程中,如果序号为n的顶点已经在S中,那么dist[n]表示从源点start到顶点n的最短距离,否则dist[n]的值将在程序执行过程中不断收敛。
    • 路径数组previous: 当程序执行完成之后,previous[n]表示最短路径中顶点n的前一个顶点

    程序执行时,每轮循环中,对Q中每个顶点u,计算源点经由S中顶点直接到达u的路径长度最小值,存入dist数组中,每轮循环只往S中加入一个顶点,这个顶点是Q中顶点dist值最小的那个,因此这是个贪心策略,为什么贪心策略是正确的?

    • Dijskstra默认每条边都是正权值
    • 因为S中的顶点的最短路径已经找到,所以加入的这个点肯定找不到一条更短的到源点的路径,否则说明S中的路径不是最短路径。

    3.实现说明

    实现时,Dijkstra算法可能会有多种改进,比如图用邻接表的形式存储,可以在稀疏图中获得更快的时间,然后计算dist最小值可以用最小堆来实现,这样就不必每次线性查找

    4.一个例子(图片来源

    image

    5.代码实现

    //aouthor:areslipan
    vector<int> Dijkstra(vector<vector<int> > &g, int vNum,int start)
    {
    vector<int>path(vNum,-1);//-1表示路径未找到
    vector<int>dist(vNum,MYINF);
    dist[start]=0;
    set<int>source;//一旦一个点距离源点start最短路径被找到,那么该点就被加入集合source中
    set<int>dest; //source 的补集
    for(int i=0;i<vNum;++i)dest.insert(i);


    set<int>::iterator iter_s;
    set<int>::iterator iter_d;

    int cur=start;

    while(!dest.empty())
    {
    int curMin=MYINF;

    //选出dest中dist最小的那个归入source中
    for(iter_d=dest.begin();iter_d!=dest.end();++iter_d)
    {
    if(curMin>dist[*iter_d])
    {
    curMin=dist[*iter_d];cur=*iter_d;
    }
    }

    source.insert(cur);
    dest.erase(cur);

    //加入一个新顶点之后开始更新dest中顶点的dist值,此处可以用最小堆优化
    for(iter_s=source.begin();iter_s!=source.end();++iter_s)
    {
    for(iter_d=dest.begin();iter_d!=dest.end();++iter_d)
    {
    if((g[*iter_s][*iter_d]+dist[*iter_s])<dist[*iter_d])
    {
    dist[*iter_d]=g[*iter_s][*iter_d]+dist[*iter_s];
    path[*iter_d]=*iter_s;
    }
    }
    }
    }

    return path;
    }

    上面这个程序算法时间复杂度较高,在优化实现的时候算法复杂度可以降低到O(NlgN),分析见wiki,这个程序只是作为说明的用途。

    6.完整的程序文件

    图算法框架

    7.参考

    参考1:http://www.wutianqi.com/?p=1890

    参考2: wiki

    参考3:文中链接

  • 相关阅读:
    Sort
    MyOD
    Linux C语言编程基础(必做)
    团队作业(一):团队展示
    2.3.1测试
    《Unix/Linux系统编程》第四章学习笔记
    课堂测试2
    课堂测试
    第三章 Unix/Linux进程管理学习笔记
    团队作业(二):需求分析
  • 原文地址:https://www.cnblogs.com/obama/p/3347114.html
Copyright © 2020-2023  润新知