程序员视角科普生活知识 hello大家好 我是浩说 关于最短路线这个问题 我们生活中有一个典型应用: 使用导航软件帮我们规划从出发地到目的地的最短路线 今天我们就来研究一下:导航软件如何计算最短路线 抽象 首先我们需要将导航软件中的地图抽象成一种数据结构:图 关于图的介绍,我用一张图片做简单说明 图的更多详细内容兄弟们可以过一下我之前的文章 于是我们可以这样对应: 顶点地图上的路口 边两个路口间的道路 入度和出度道路的方向 边的权重两个路口间的距离 按照上面的思路我们抽象成图就是这样的: 数据结构是为算法服务的,我们将地图抽象成数据结构图之后, 下一步就是在该数据结构上设计出一种算法来计算出最短路线。 点个赞,证明你还爱我 算法 针对求最短路径的场景,有一种经典的算法叫做: Dijkstra算法由荷兰计算机科学家EdsgerWybeDijkstra在1956年发现 这也就是我们本篇的重点了, 算法问题很难用一两句话解释清楚,所以接下来我将分步骤拆解应用Dijkstra算法计算最短路径的过程, 大家需要从过程中感受和体会Dijkstra算法的思路和原理。 先将图中每个顶点用编号表示,目标就是计算顶点1到8的最短距离 接着我们准备两个数组: 一个数组存放图中除起点以外的所有顶点V{2,3,4,5,6,7,8} 另一个数组先存放起点S{1} 我们以起点1为原点,逐步统计其它顶点到原点的距离,无法直接到达的顶点距离用表示 1hr统计结果如下: dist12:270 dist13:300 dist14: dist15:200 dist16: dist17: dist18: 然后通过比较上面的结果选择最小的值,也就是dist15,至此Dijkstra算法会暂时认定: 顶点1到5的最短距离为200。 此时将顶点5从数组V中移除,并添加至数组S: V{2,3,4,6,7,8} S{1,5} 所以数组S中的顶点其实就是表示已经找到从原点到对应顶点的最短距离的顶点集。 经过此步骤后,Dijkstra算法暂时认定找到了从原点1至顶点5的最短路径,我们用绿色表做标记。 2hr该步骤与上一步逻辑相同,但区别在于: 由于我们找到了到达顶点5的最短路径,所以之前无法到达的顶点(4、6),在该步骤就可以通过顶点5间接的到达了 于是再次统计距离 dist12:270 dist13:300 dist1415(200)54(260):460 dist15:200 dist1615(200)56(310):510 dist17: dist18: 除去已经被加入到数组S中的顶点,我们依然从剩下的距离中选出最短的,然后将该顶点从数组V移除并加入数组S V{3,4,6,7,8} S{1,5,2} 看到这里相信大家已经对Dijkstra算法的逻辑有点感觉了,我们不妨简单梳理一下: Dijkstra算法需要准备两个数组,一个存放从起点至终点涉及到的所有顶点,另一个存放已经确定最短路径的顶点, 然后从原点开始,循环查找至下一顶点距离最短的顶点并将其从V移除然后添加至S中,直至V中顶点全部添加至S中。 当然,这其中还有一些细节需要注意,我们继续往下看。 3hr细节来了,注意看这里的顶点4,由于前两步我们打通了顶点2、5的最短距离,因此到达顶点4的路径有两条: dist14 15(200)54(260):460 12(270)24(210):480 而此时Dijkstra算法将取距离小的作为最终结果。 最终统计的距离 dist12:270 dist13:300 dist1415(200)54(260):460 dist15:200 dist1615(200)56(310):510 dist17: dist18: 距离最短的顶点为3: V{4,6,7,8} S{1,5,2,3} 4hr这一步顶点6和上一步顶点4出现了一样的情况, 由于我们打通了顶点3,所以到达顶点6的路径变成了两条 dist16 15(200)56(310):510 13(300)36(180):480 依然选择距离短的作为最终结果。 dist12:270 dist13:300 dist1415(200)54(260):460 dist15:200 dist1613(300)36(180):480 dist17: dist18: 顶点4加入S: V{6,7,8} S{1,5,2,3,4} 看到这一步相信大家对Dijkstra算法的逻辑和一些细节已经有了大体的感受,后面的步骤就很好理解了,我们继续往下看。 5hrdist12:270 dist13:300 dist1415(200)54(260):460 dist15:200 dist1613(300)36(180):480 dist1714(460)47(130):590 dist18: 顶点6加入S: V{7,8} S{1,5,2,3,4,6} 6hrdist12:270 dist13:300 dist1415(200)54(260):460 dist15:200 dist1613(300)36(180):480 dist17:14(460)47(130):590 dist18:16(480)68(100):580 V{7} S{1,5,2,3,4,6,8} 7hrdist12:270 dist13:300 dist1415(200)54(260):460 dist15:200 dist1613(300)36(180):480 dist17:14(460)47(130):590 dist18:16(480)68(100):580 V{} S{1,5,2,3,4,6,8,7} 到这一步数组V已经为空,Dijkstra算法就到此结束了。 兄弟们可能会有疑问,因为在下图中,由顶点7至顶点8这条路线并没有做判断,难道是Dijkstra算法有问题吗? 我们回看一下刚才距离的计算结果 dist17:14(460)47(130):590 dist18:16(480)68(100):580 既然dist17已经大于dist18, 那么dist17dist78必然是会大于dist18的,所以这是符合逻辑的,无需再判断了。 到这里Dijkstra算法就成功的帮我们规划出了最短路线: dist1813(300)36(180)68(100):580 听说好看的人都点赞分享了哦!