正确理解Dijkstra(迪杰斯特拉)算法

下面给出一张在各大计算机网络教材中使用的经典例图。


我们的目的是求出A到各点的最短路径,初始集合U={A,B,C,D,E,F}。取元素的规则是取当前A到各点最短且没被取过的点(即在U中的点)


我们一开始从U中取出A,并更新各点距离。当前A到D=1,A到B=2,A到另外的点的距离是无穷大,所以我们取出D。

正确理解Dijkstra(迪杰斯特拉)算法_第1张图片


取出D后A到各点的距离。当A打算A->D->B作为A到B的最小路径3的时候,发现更新不了,因为原来AB是2,更短,更新失败。这里B、E两点可以任取。我们取E。

正确理解Dijkstra(迪杰斯特拉)算法_第2张图片


到达E点后,A到各点的最短距离如下图所示。成功更新C点的最短距离为1+1+1=3。这里就是重点了。发现A到B最短,所以我们直接取B了!

正确理解Dijkstra(迪杰斯特拉)算法_第3张图片


下面给出取B后的A到各点的距离,B视图用2+3去更新C,发现更新不了。这里就取C了。取了C试图带着3+5=8去更新F,发现更新不了。最后取出F,所有点都取完了,A到每个点的最短距离都已经显示出来了。

正确理解Dijkstra(迪杰斯特拉)算法_第4张图片


接下来是原理剖析。


首先明白一点,我们不是一个个点走下去的,而是一个个点取下去的。如果你认为Dijkstra算法是靠走的,那么你在取完E后再取B的这个过程十分疑惑了。


此外为什么要以这种形式取呢?其实大可不必。上面的Dijkstra算法是优化过的Dijkstra算法。最原始的Dijkstra算法是任意从U中取一个点,然后以此更新另外不管取过没取过的所有的点。


我们优化过的算法就很聪明了,我们取过的点,我们就不再更新他了!可是问题来了,我们不更新他,最终的出来的结果不会错吗?当然会错,所以我们采取的措施是取元素的规则是取当前A到各点最短且没被取过的点(即在U中的点)。为什么这样的取法就可以规避更新我们取过的点呢?其实从最小开始更新不会错,但是假如说你不是这样一个取法,你可能会发现你会率先取到大的值,但是你当你取的小的数,但是因为大的数已经取过了,你更新不了他了,但是事实上他有更小的解,这个时候就错了。详细可以看我的-深入理解Dijkstra(迪杰斯特拉)算法-的解析部分:http://blog.csdn.net/qq_36523667/article/details/78779272

你可能感兴趣的:(算法知识)