大家如果对几种最短路算法有一个基本的了解,大概会有一种模糊的感受,dijkstra是一个“加点”的过程,floyd是一个“选线”的过程。
Dijkstra
dijkstra很多教程都讲分成两个集合,但事实上写代码的时候并不需要,那为什么还要提这个呢,就是为了强化大家“从T集选点加入S集”这个观念。S集的特性是,里面所有的点都已经确定了它的最短距离了。待到所有的点都加入S集,那么问题就解决了
但是这个过程并不直观,为什么说现在优先队列里最短的那条边的另一个端点就是下一个要加入S的点呢?很多教程的例图都画的像PERT图一样,从左到右,边的设计也是非常不符合三角形两边之和大于第三边,我不是说不存在这样的情况,主要是会导致在纸上画不出来,长为10的边比长为3的边还短,很难直观,不适合人类去理解。我换种形式,大家就懂了
圈内的所有点的集合就是S集,刚入圈的新成员是A点。圈内所有点离O的距离都是<=OA的
假如我们现在想扩圈,找到一个新点加进来,那当然是既要考虑与A相连的点们(蓝线),又要考虑与圈内其他点相连的点们,比如和B相连的点(绿线)。而具体选哪一个,就要看这几个点谁离O最短了,对于A的朋友们X是OA+AX,对于B的朋友们是OB+BY。这也是为什么我们要将A相邻的所有边加入优先队列中。B的朋友们已经在了,就不用加了。
这个过程什么时候结束呢,就是当优先队列所有的线都被处理完了。这个圈子是被慢慢扩大的,只要圈外还有点,肯定是要继续向外伸线,不会漏掉哪个点;所有线处理完了,所有的点也处理完了,这个时候可以break这个while了
一些细节:
- G也是A相连的点,但是没必要考虑把G放进优先队列中,即OG<OA+AG时无需处理