2021-06-04 从例题看Dijkstra算法

/背景/
在图论的学习中,非常有实用性的一个课题:最短路径。
这里讨论一下Dijkstra算法求最短路径。
**用于图中某一顶点到其余各顶点的最短路径。

/理论/
Dijkstra的主要思想是分两个集合存放结点。S集合存放已确定路径会经过的顶点,T集合存放暂时查到最短路径但还未确定的顶点。从出发点开始,每次遍历S集合最新节点的可达到节点路径,计算最短路径后存入T集合,最短路径到达的节点入S集合,直至所有节点遍历结束。这个算法的主要思想也可以用贪心算法来总结。每次获取下一段最短路径,上一段都已经是最短路径。

/实 现/

Dijkstra的实现主要使用三个辅助数组。

  1. dist[]表示当前S最新节点至可到达节点的最短距离。不可直达的暂不计算。
  2. path[]表示当前S最新节点最短路径的上一个节点。
  3. set[]标记已入S集合的节点。

来看一道例题,了解下算法。


WX20210604-142221@2x.png

以顶点0为起点:

dist[1] = 4 < dist[2] = 6 < dist[3] = 6
dist[4] = dist[1] + dist[1][4] = 11
以1为中转点检测

0 1 2 3 4 5 6
Dist 0 4 5 6 11 - -
Path -1 0 1 0 1 -1 -1
Set 1 1 0 0 0 0 0

dist[2] = 6 > dist[1] + dist[1][2] = 5
dist[3]=6 < dist[1] + dist[1][2] + dist[2][3] = 7 < dist[2] + dist[2]dist[3] = 8
dist[4] = dist[1]+dist[1][4] = 11 (以下省略遍历步骤,只给出最短路径)
dist[5] = dist[1] + dist[1][2] +dist[2][5] = 9
以2为中转点检测

0 1 2 3 4 5 6
Dist 0 4 5 6 11 9 -
Path -1 0 1 0 1 2 -1
Set 1 1 1 0 0 0 0

dist[4] = 11
dist[5] = 9
以3位中转点检测

0 1 2 3 4 5 6
Dist 0 4 5 6 11 9 -
Path -1 0 1 0 1 2 -1
Set 1 1 1 1 0 0 0

** dist[4] = dist[1] + dist[1][2] + dist[2][5] + dist[5][4] = 10 (注意:此处更新了4的路径)
** dist[6] = dist[1] + dist[1][2] + dist[2][5] + dist[5][6] = 17 (注意:此处4还未入S集合,所以最短路径只能走5)
以5为中转点检测(因为5比4路径短)

0 1 2 3 4 5 6
Dist 0 4 5 6 10 9 17
Path -1 0 1 0 1 2 5
Set 1 1 1 1 0 1 0

dist[5] = 9
dist[6] = dist[1] + dist[1][2] + dist[2][5] + dist[5][4] + dist[4][6] = 16
以4为中转点检测

0 1 2 3 4 5 6
Dist 0 4 5 6 10 9 16
Path -1 0 1 0 5 2 4
Set 1 1 1 1 1 1 0

所有节点并入

0 1 2 3 4 5 6
Dist 0 4 5 6 10 9 16
Path -1 0 1 0 5 2 4
Set 1 1 1 1 1 1 1

再来看一下实现代码:

// 图的定义 顺序存储
typedef struct
{
    int edges[maxSize][maxSize];
    // 邻接矩阵定义,如果是有权图,则在此句中将int改为float
    int n, e; // 分别为顶点数和边数
    VertextType vex[maxSize];
}MGraph;

// Dijkstra path数组。内容是一棵双亲存储结构的树。
void printfPath(int path[], int a)
{
    int stack[maxSize], top = -1;
    while (path[a] != -1)
    {
        stack[++top] = a;
        a = path[a];
    }
    stack[++top] = a;
    while (top != -1)
    {
        cout<<stack[top--]<<" "; 
    }
    cout<<endl;
    
}

//Dijkstra
void Dijkstra(MGraph g, int v, int dist[], int path[])
{
    int set[maxSize];
    int min, i, j, u;
    // 初始化各个数组
    for ( i = 0; i < g.n; ++i)
    {
        dist[i] = g.edges[v][i];
        set[i] = 0;
        if (g.edges[v][i] < INF)
        {
            path[i] = v;
        }
        else
        {
            path[i] = -1;
        }
        
    }
    set[v] = 1;
    path[v] = -1;
    // 初始化结束 开始关键操作
    for ( i = 0; i < g.n-1; ++i)
    {
       min = INF; // INF是一个常量 要比所有权值大 为了获得最小值
       for ( j = 0; j < g.n; ++j) // 每次从未入S集合的点中获取路径最短的点
       {
           if (set[j] == 0 && dist[j] < min)
           {
               u = j;
               min = dist[j];
           }
           
       }
       set[u] = 1; // 入S集合
       
       for ( j = 0; j < g.n; ++j)
       {
           if (set[j]==0 && dist[u] + g.edges[u][j] < dist[j]) // 如果有更短的路径 进行更新
           {
               dist[j] = dist[u] + g.edges[u][j];
               path[j] = u;
           }
           
       }
       
    }
    
}

有时候看文字看不懂,可以考虑做题试试,也许迎刃而解 :P

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容