算法基础篇(5)------最短路

来源:互联网 发布:淘宝代运营怎么找客户 编辑:程序博客网 时间:2024/06/06 02:57

● 每周一言

成功,没有捷径。

导语

最短路问题是生活中比较常见的问题了,比如交通运输规划、出行线路规划等,都需要用到最短路算法。那么常用的最短路算法有哪些?它们分别是如何实现的?

最短路

我们不妨按照全局最短路、单源最短路和点对点最短路对算法进行分类如下:

全局最短路:Floyd
单源最短路:Dijkstra、Bellman-ford、SPFA
点对点最短路:DFS/BFS

fig1

Floyd算法 该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。Floyd算法应该是最好理解也是最好实现的最短路算法了,它可以求出一个图中任意两点之间的最短路。算法思想是动态规划,如下图所示,时间复杂度为O(V^3)。
fig2

Dijkstra算法 Dijkstra(迪杰斯特拉)算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,解决的是有向图中的单源最短路径问题。其基本思想是以起始点为中心,每次选一个距离起始点最近的点,然后扩展该点相连边相接的直达点,扩展点数-1次算法终止。注意,迪杰斯特拉算法无法计算带复权的图。算法流程图如下图所示,时间复杂度为O(V^2)。

fig3

Bellman-ford算法 该算法由美国数学家理查德•贝尔曼(Richard Bellman, 动态规划的提出者)和小莱斯特•福特(Lester Ford)发明,可以计算上述迪杰斯特拉算法无法计算的带复权的情形,能识别出复权回路。其算法思想分如下三步,时间复杂度为O(VE)。

1> 初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达);
2> 进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算(边优化点距离);
3> 遍历途中所有的边edge(u, v),判断是否存在这样情况:d(v) > d (u) + w(u, v)。则返回false,表示途中存在从源点可达的权为负的回路。

流程图如下:

fig4

SPFA算法 该算法的全称是Shortest Path Faster Algorithm,由西南交通大学段凡丁于1994年提出。由于Bellman-ford算法的松弛计算每次都需要遍历所有边,因此算法复杂度偏高,尤其是当边数趋于饱和的情况下。而SPFA算法是Bellman-ford算法的队列优化版本,其通过队列优化加速松弛操作。具体方法是用邻接表存储边,外层点循环改为队列,每次松弛操作依据邻接表只取相关的边松弛,如果点的距离有更新,则将该点重新加入队尾,直到队列为空。当然,SPFA遇到复权回路也会无限松弛下去。这里值得一提的是,SPFA在解决网络流问题中效果不错。

fig5

DFS/BFS算法 点对点最短路最直观的算法应该是DFS(深度优先搜索)算法和BFS(宽度优先搜索)算法了,算法的时间复杂度均为O(E)。由于篇幅关系,这里就不再对搜索作进一步描述。

敬请期待下节内容 线段树

结语

感谢各位的耐心阅读,后续文章于每周日奉上,欢迎大家关注小斗公众号 对半独白

face

0 0