首页 | 主题 | 图库 | 问答 | 文摘 | 原创 | 百科

历史 | 地理 | 人物 | 艺术 | 体育 | 科学 | 音乐 | 电影 | 信息技术 | 世界遗产

 开放、中立,源自维基百科

个人工具


用搜狗搜索相关网站  Google Search

Dijkstra算法

维库,知识与思想的自由文库

(重定向自戴克斯特拉算法)
跳转到: 导航, 搜索


Dijkstra算法是由丹麦计算机科学家Edsger Dijkstra发现的。算法解决的是有向图中最短路径问题。

舉例來說,如果圖中的頂點表示城市,而邊上的權重表示著城市間開車行經的距離。 Dijkstra演算法可以用來找到兩個城市之間的最短路徑。

Dijkstra演算法的輸入包含了一個有權重的有向圖G,以及G中的一個來源頂點S。 我們以V表示G中所有頂點的集合。 每一個圖中的,都是兩個頂點所形成的有序元素對。(u,v)表示從頂點uv有路徑相連。 我們以E所有邊的集合,而邊的權重則由權重函數w: E → [0, ∞]定義。 因此,w(u,v)就是從頂點u到頂點v的非負花費值(cost)。 邊的花費可以想像成兩個頂點之間的距離。任兩點間路徑的花費值,就是該路徑上所有邊的花費值總和。 已知有V中有頂點st,Dijkstra演算法可以找到st的最低花費路徑(i.e. 最短路徑)。 這個演算法也可以在一個圖中,找到從一個頂點s到任何其他頂點的最短路徑。

目录

[编辑] 算法描述

这个算法是通过为每个顶点v保留目前为止所找到的从s到v的最短路径来工作的。初始时,源点s的路径长度值被赋为0(d[s]=0), 同时把所有其他顶点的路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径(对于V中所有顶点vsd[v]= ∞)。当算法结束时,d[v]中储存的便是从sv的最短路径,或者如果路径不存在的话是无穷大。 Dijstra算法的基础操作是边的拓展:如果存在一条从uv的边,那么从su的最短路径可以通过将边(u,v)添加到尾部来拓展一条从s到v的路径。这条路径的长度是d[u]+w(u,v)。如果这个值比目前已知的d[v]的值要小,我们可以用新值来替代当前d[v]中的值。拓展边的操作一直执行到所有的d[v]都代表从s到v最短路径的花费。这个算法经过组织因而当d[u]达到它最终的值的时候没条边(u,v)都只被拓展一次。

算法维护两个顶点集S和Q。集合S保留了我们已知的所有d[v]的值已经是最短路径的值顶点,而集合Q则保留其他所有顶点。集合S初始状态为空,而后每一步都有一个顶点从Q移动到S。这个被选择的顶点是Q中拥有最小的d[u]值的顶点。当一个顶点u从Q中转移到了S中,算法对每条外接边(u,v)进行拓展。

[编辑] 伪码

在下面的算法中,u:=Extract_Min(Q)在在顶点集Q中搜索有最小的d[u]值的顶点u。这个顶点被从集合Q中删除并返回给用户。

 1  function Dijkstra(G, w, s)
 2     for each vertex v in V[G]                        // 初始化
 3           d[v] := infinity
 4           previous[v] := undefined
 5     d[s] := 0
 6     S := empty set
 7     Q := set of all vertices
 8     while Q is not an empty set                      // Dijstra算法主体
 9           u := Extract_Min(Q)
10           S := S union {u}
11           for each edge (u,v) outgoing from u
12                  if d[v] > d[u] + w(u,v)             // 拓展边(u,v)
13                        d[v] := d[u] + w(u,v)
14                        previous[v] := u

如果我们只对在st之间寻找一条最短路径的话,我们可以在第9行添加条件如果满足u=t的话终止程序。

现在我们可以通过迭代来回溯出st的最短路径

1 S := empty sequence 
2 u := t
3 while defined u                                        
4       insert u to the beginning of S
5       u := previous[u]

现在序列S就是从st的最短路径的顶点集.

[编辑] 时间复杂度

利用大O,我们可以把Dijkstra算法运用在一个有m条边和n个点的图上的运行时间表达成一个关于m和n的函数。

Dijkstra算法的最简单实现是把集合Q里面的点存进一个已经链接好的链表或者数组中,而操作Extract-Min(Q)就只需在所有这些点中作线性搜索。在这种情形下,运行时间是O(n)。

对于稀疏图,就是那种边数少于n的图,通过把图保存为邻接表的形式,并用二元堆或者斐波那契堆构造出Extract-Min函数,Dijkstra算法可以更有效地实现。若用二元堆,算法的时间复杂度为O(m+n),若用斐波那契堆,算法的时间复杂度则提高为 O(m+nlogn)。

[编辑] 相关问题和算法

The functionality of Dijkstra's original algorithm can be extended with a variety of modifications. For example, sometimes it is desirable to present solutions which are less than mathematically optimal. To obtain a ranked list of less-than-optimal solutions, the optimal solution is first calculated. A single edge appearing in the optimal solution is removed from the graph, and the optimum solution to this new graph is calculated. Each edge of the original solution is suppressed in turn and a new shortest-path calculated. The secondary solutions are then ranked and presented after the first optimal solution.

OSPF (open shortest path first) is a well known real-world implementation of Dijkstra's algorithm used in internet routing.

Unlike Dijkstra's algorithm, the Bellman-Ford algorithm can be used on graphs with negative edge weights, as long as the graph contains no negative cycle reachable from the source vertex s. (The presence of such cycles means there is no shortest path, since the total weight becomes lower each time the cycle is traversed.)

A related problem is the traveling salesman problem, which is the problem of finding the shortest path that goes through every vertex exactly once, and returns to the start. This problem is NP-hard; in other words, unlike the shortest path problem, it is unlikely to be solved by a polynomial-time algorithm.

If additional information is available that estimates the "distance" to the target, the A* algorithm can be used instead to cut down on the size of the subset of the graph which is explored.

[编辑] 参考

[编辑] 外部链接

其它语言
AD Links