Dijkstra算法是一种最短路径算法,用于计算一个节点到其它所有节点的最短路径,动态路由协议OSPF中就用到了Dijkstra算法来为路由计算最短路径。
算法本身并不是按照我们的正常思维习惯,我们一般会,从原点遍历所有与之相连的节点,找到最短路径,再从最短路径上的那个点遍历与之相连的所有其它点(原点除外),然后依次类推。这样做虽然可以算出一个树形,但是在大多数情况下,这种算法会产生很多次优路径,也就是说非最短路径。
Dijkstra算法的大概过程:
假设有两个集合或者说两个表,表A和表B
表A表示生成路径,表B表示最后确定的路径
1.从原点出发,遍历检查所有与之相连的节点,将原点和这些节点存放到表A中,并记录下两节点之间的代价。
2.将代价最小的代价值和这两节点移动到表B中(其中一个是原点)。
3.把这个节点所连接的子节点找出,放入到表A中,算出子节点到原点的代价
4.重复第二步和第三步直到表A为空。然后根据表B中的数据算出最优树。
维基百科中还有另一种说法,Dijkstra算法的输入包含了一个有权重的有向图G,以及G中的一个来源顶点S。 我们以V表示G中所有顶点的集合。 每一个图中的边,都是两个顶点所形成的有序元素对。(u,v)表示从顶点u到v有路径相连。 我们以E所有边的集合,而边的权重则由权重函数w: E → [0, ∞]定义。 因此,w(u,v)就是从顶点u到顶点v的非负花费值(cost)。 边的花费可以想像成两个顶点之间的距离。任两点间路径的花费值,就是该路径上所有边的花费值总和。 已知有V中有顶点s及t,Dijkstra算法可以找到s到t的最低花费路径(i.e. 最短路径)。 这个算法也可以在一个图中,找到从一个顶点s到任何其他顶点的最短路径。
Dijstra算法的基础操作是边的拓展:如果存在一条从u到v的边,那么从s到u的最短路径可以通过将边(u,v)添加到尾部来拓展一条从s到v的路径。这条路径的长度是d[u]+w(u,v)。如果这个值比目前已知的d[v]的值要小,我们可以用新值来替代当前d[v]中的值。拓展边的操作一直执行到所有的d[v]都代表从s到v最短路径的花费。这个算法经过组织因而当d[u]达到它最终的值的时候没条边(u,v)都只被拓展一次。
Dijkstra算法图示:
自己写的每次更新后的所对应的一些顶点和距离的变化
S U
{1} {2,3,4,5,6} {0,2,4,∞,∞,∞}
{1,2} {3,4,5,6} {0,2,3,6,4,∞}
{1,2,3} {4,5,6} {0,2,3,6,4,∞}
{1,2,3,5} {4,6} {0,2,3,6,4,6}
{1,2,3,5,4} {6} {0,2,3,6,4,6}
{1,2,3,5,4,6} {} {0,2,3,6,4,6}