![3ccc077ea6e43772879baccb7019dc83.png](https://i-blog.csdnimg.cn/blog_migrate/a6c59db8b43d9a0b62577bc82d87dbb2.jpeg)
dijkstra算法(迪杰斯特拉算法)是荷兰科学家E.W.Dijkstra于1959年提出的寻路算法,是目前公认的最好的求解最短路径的方法。堆优化后时间复杂度可达O((m+n)log(m)),但缺点是不能处理负权边。
负权边是什么:负权边,即权重为负的边。我们可以将每一条边的权重可以认为是从a端到b市面的过路费,而负权就是有土豪在地上撒钱,不但没有过路费还会让你总花费变少。
其算法步骤如下
- 将所有的顶点分为两个部分:已知最短距离的顶点集合P和未知最短距离的顶点集合Q。最开始的时候,已知最短距离的顶点集合中只有源点。
- 初始化distance数组,将源点s到自己的距离设置为0,到其他顶点的距离姑且设置为Infinity。
- 依据distance数组,在未知顶点集合Q中选出距离源点最近的一个顶点u,放入P中,并考察所有以u为起点的边,以u作为中转点,检验是否能够减短源点到其他点的距离。如果有,就更新distance数组。这一步又叫松弛(relaxation)操作。
- 重复上一步骤,直到Q中没有顶点。
松弛操作:更新两点间的最短路径。就是对于每个边e(v,w),将源点s到w的距离更新为:原来源点s到w的距离 和 源点s到v的距离加上v到w的距离 中较小的那个。其原理是著名的“三角形两边之和大于第三边”定律。
![a8cced81cbe97ab7f4782cad90ffc4ad.png](https://i-blog.csdnimg.cn/blog_migrate/5fa18833143f7b8b6fc7690d3ef7d6b4.jpeg)
下面我们图解整个算法过程:
![75c40e6a515ea559ea1e8e8e71630dea.png](https://i-blog.csdnimg.cn/blog_migrate/31ce15e946103c7761e3fde02e908e91.jpeg)
从A出发,到达A
var
![c527dc5cf7109cf078cd491884d4d3f9.png](https://i-blog.csdnimg.cn/blog_migrate/cb3592393f6e613b4fd99c5c7ded5ee4.jpeg)
寻找A的没被访问的邻居顶点B,D,分别计算它们到A的距离
A
![7c7cfb610d00a0f992d8b21e16bf113a.png](https://i-blog.csdnimg.cn/blog_migrate/08fe8229b2a28b9a499078fae0ad88ff.jpeg)
将距离最短的D放到S集合中
var
寻找D的没被访问的邻居顶点B,C,E,分别计算它们到A的距离
A
D到B,D的距离一样,都放入结果集
var
![165f30a2e8a689819c889456ac088aad.png](https://i-blog.csdnimg.cn/blog_migrate/e2a87d785131fa369a266ce29f059f94.jpeg)
这时可以从B与C出发,但B已经没有未访问的邻居,而C有一个E
A->D->C->E = S.C+ E.weight = 3+3 = 6
将E放到结果集中
var
![4be8758f3bbf17190ecc7c4e96711d47.png](https://i-blog.csdnimg.cn/blog_migrate/a8331b6e620aaacfb5a2099fa6102bcf.jpeg)
我们顺着上面的思路,使用链式前向星与BFS实现该算法。BFS会在循环中将它的所有邻居放在一起比较到源点的距离,因此我们还需要排序(这在其他语言,可以用到优先队列)。
var
![c9d8df9ec735a9aef03172c6230d9044.png](https://i-blog.csdnimg.cn/blog_migrate/2de096a0ade54d053aa3d8599416e820.jpeg)
对于无权图,所谓的最短路径其实是指两顶点之间经过的边数最少的路径。
如果 你不会用链式前向星,改用边集数组来表示图也很简单
var
![0599ced64c59088d362366cde3511020.png](https://i-blog.csdnimg.cn/blog_migrate/9762a44a12c7ca82f24cf51c1bd1ec0e.jpeg)