简述一下Dijkstra算法
先举个例子来简述一下Dijkstra算法吧。如下图,从节点1出发,求到每个节点的最短路径
首先获取节点1到各个节点的距离,需要注意的是,我们给算法的输入数据是一个邻接矩阵或者邻接表,从这个邻接矩阵里我们能获取到的只有相邻节点的距离(同时也是最短距离),而其余的暂时未知,全部设为无穷大。
接下来就是循环重复这三个动作:
在尚未被排除的节点中,找到目前与①距离最短的那个节点(姑且称这个节点为V)
比如在上图中,②③④⑤都是尚未排除的节点,从刚刚第一步的操作我们可以知道,①到②的距离是2,到③的距离是5,其余都是无穷大。那么目前与①距离最短的节点就是②,V=②
找到节点V之后的节点,把自己的路径“借”给它们,看看能不能更新它们的最短路径
②之后的节点是③和④,
先考虑③节点:从①到②的路径长度是2,而②到③的长度是2,所以“从①到②再到③”这个路径的长度是2+2=4。而如果直接从①到③,长度则是5,5大于4,显然是“从①到②再到③”这条路径更优。所以③的路径更新为“①>②>③”,长度为4。
再考虑④节点:而②到④的长度是6,所以“①>②>④”这个路径的长度是2+6=8,而如果直接从①到④,就目前掌握的数据而言,长度是无穷大。所以从①到④的路径更新为“①>②>④”,长度为8。
放在具体的编程里,我们就是要为每个节点都建立一组数据,定义一个结构体,包含:路径,路径长度。
但其实可以优化一下,并不需要把路径从头到尾记录下来,只需要记录这个节点的前一个节点是谁就好。比如④的前节点是②,②的前节点是①,如果你想知道从①到④的路径,就可以从④开始,④会找到②,②会找到①,就得到完整的路径了。
把检查过的节点排除掉,以后不再检查
刚刚检查了②,那么现在就可以把②排除了(图里排除的用红色圈起来了)
放在具体的编程里,我们可以建立一个集合,包含未被排除的节点:
vector<节点指针> Vset={2,3,4,5};
然后在排除的时候直接remove
Vset.remove(2);
上面这样写只是方便理解,实际编程还要具体考虑
如果还不理解的话可以看这位大佬的文章:Dijkstra算法详解(完美图解、趣学算法)
准确性证明
这个算法凭什么保证它求得的一定是最短路径呢?
我们可以这样思考:
比如我们要 求这个图中的节点⑤的最短路径,
对于节点⑤,只有两种到达它的方法,
一个是通过节点③,一个是通过节点④
“可是通过节点④的路径也有很多条呀?比如‘①>②>④>⑤’或‘①>③>④>⑤’。”
这个问题我们暂且不关心,假设我现在已经掌握了从①到④的最短路径,那么在这个前提下,我可以断定,通过这个从①到④的最短路径再到达⑤的路径,一定是在通过节点④到达节点⑤这个方法中最短的路径。
然后,假设我还拿到了从①到③的最短路径,那么通过这个从①到③的最短路径再到达⑤的路径,一定是在通过节点③到达节点⑤这个方法中最短的路径。
而对于这个图中的节点⑤,你只有两种方法可以到达它
要么是通过节点③,要么是通过节点④
那么只要我对比这两个“通过③的最短路径”和“通过④的最短路径”哪个更短,不就确定了从①到⑤的最短路径了吗?
如果你能理解上面的思路,那么整个问题其实已经证明完毕了。具体的推导就交由读者自己动笔吧。
但其实还有一个关键问题没有解决
你凭什么保证这个节点在被检查到之前就已经拿到了它的最短路径?
比如还是这张图的节点④(稍微改改),可以看出它的最短路径是“①>⑥>⑦>④”,那万一好巧不巧,算法先走了“①>②>④”,然后到了④,那么节点⑤就会把①>②>④>⑤当作最短路径,可实际上正确的最短路径应该是“①>⑥>⑦>④>⑤”
会不会出现这种情况呢? 依照算法跑一遍,发现其实不会。
为什么?
接下来就要证明:
一个节点在被检查之前,必定已经找到了它的最短路径。
<=逆否命题=>
若某一节点存在更短的路径却尚未被选中,则这个节点不可能被检查
证明开始:
让我们回顾一下这个步骤:
在尚未被排除的节点中,找到目前与①距离最短的那个节点(姑且称这个节点为V)
这个步骤它保证了什么呢?
假如现在有两条路径,红色的路径算法已经跑过了,并且知道它的长度是13;紫色的路径紫色的路径算法跑了一半,还不知道最终长度,那么算法会选择放弃紫色路径直接奔向节点④吗?答案是不会。因为2+8=10<13,下面这条没跑完的路径更短,所以算法肯定会先去跑紫色路径。
那么如果我现在不知道具体的数值,只知道紫色路径比红色路径短(算法程序不知道),可以保证算法一定会选紫色路径吗?
证:
记红色路径长度为a,紫色路径长度为b,且a>b
在程序中,紫色路径尚未跑完,假设紫色路径中途停在了某个节点V处,记录在案的路径长度为r,显然,在这条紫色路径上,从①到途经点V的距离一定小于从①到终点的距离,也就是r<b
又已知a>b,所以a>r,所以算法在检查节点④之前一定会去检查节点V
证毕
peace