本文首先讲解原理 后讲解源代码
原理
DIJ算法,迪杰斯特拉算法,求最短路径
给出一张图,给出各个点间的距离(不能到达视为无穷大),给出一个顶点,将之视为出发点,求出这个点到其余所有点的最短路径。
思想介绍 两个集合 S 和U ,S集合最开始只有给定的出发点,U集合是除了出发点之外的所有点。U集合中所有点都表示为 距离出发点距离xxx的点,
例如 S{A} U{ B(4),C(7),D(无穷大)}这样表示
最开始把U中距离出发点最小的加入到S集合中,并且要审查U中集合是否因为S集合中点的加入,使得U中的点到出发点的距离变小了。如果有那么就要更新。
每次都执行两步操作:
1:从U集合中选择到出发点距离最小的点 加入到S集合
2:更新U集合中剩余的点到出发点的最短路
所以现在请你思考一下,这个算法实现起来的难度在哪里,当你发现这个算法哪里最难实现,那就是这个算法的核心
难点:加入新的点后,如何更新目前其它点到出发点的最短路径,因为新加入的点很可能会影响到原来的值,比如将E加入之后,原来A和C本来无法相连,距离为无穷大,但是有了E这个中间串联的,现在AC可以连接了,距离为一个确定的数。
算法实现讲解
第一步,对输入的边的顶点以及权值进行存储
非常重要的一个图的存储方式–链式前向星
以往的存储图的方式是邻接表,但是有缺陷,这是采用二维数组的方式存储,首先二维数组是非常耗费空间的,其次是两个点之间可能并不存在边。
链式前向星,只需要一个结构体以及一个head一维数组,效率极高,空间上时间上都优越不少。值得大家深入了解。
DIJ算法核心操作
首先进行边的遍历(这里采用的是链式前向星的遍历方式)
当这个顶点没有被访问过,并且当前ans值可以被优化时,进行ans值得更新操作。遍历完成之后,还要不断找最小值,进而确定pos的新的值(pos的新的值要选择ans值最小的进行下一步)
输出结果,程序结束
*总结:
本文重在强调两点,第一是摒弃传统的邻接表存储方式,改用时间空间上更为优越的链式前向星(读者可自行查阅详细信息)
第二是强调DIJ算法的核心操作,重在加入新的点之后,如何更新剩余点到初始点的最短距离*。