转自:http://www.mathcs.emory.edu/~cheung/Courses/171/Syllabus/11-Graph/dijkstra2.html
一. 图解迪杰斯特拉
- Before showing you the pseudo code, I will first execute the Dijkstra's Algorithm on the following graph:
- Find the shortest paths from the node 1 to all other nodes in the graph:
- Find the shortest paths from the node 1 to all other nodes in the graph:
- The execution of the Dijkstra's Algorithm:
- Initilaization:
- Label the source node (node 1) as reached
- Label all the other nodes as unreached
- Use each edge from the source node (node 1) as the shortest path to nodes that you can reach immediately
Result:
(The reached node(s) have a cyan circle as marking.
The unreached nodes are unmarked)
- Iteration (1):
- Find the unreached node m that has the shortest path from the source node:
- m = 2 (with path length = 3)
- Added the edge you used to reach m to the shortest path
Label the node m as reached
- Recompute the shortest paths of nodes that can be reached via m (if possible)
We can reach the node 3 via node 2 through a shorter path !!!
Result at the end of the iteration:
- Find the unreached node m that has the shortest path from the source node:
- Iteration (2):
- Find the unreached node m that has the shortest path from the source node:
- m = 3 (with path length = 5)
(Node 0 will work also, but I picked node 3)
- m = 3 (with path length = 5)
- Added the edge you used to reach m to the shortest path
Label the node m as reached
- Recompute the shortest paths of nodes that can be reached via m (if possible)
We can reach the node 4 via node 3 through a path of length 8 !!!
Result at the end of the iteration:
- Find the unreached node m that has the shortest path from the source node:
- Iteration (3):
- Find the unreached node m that has the shortest path from the source node:
- m = 0 (with path length = 5)
- Added the edge you used to reach m to the shortest path
Label the node m as reached
- Recompute the shortest paths of nodes that can be reached via m (if possible)
There are no improvements....
Result at the end of the iteration:
- Find the unreached node m that has the shortest path from the source node:
- Iteration (4):
- Find the unreached node m that has the shortest path from the source node:
- m = 4 (with path length = 8)
- Added the edge you used to reach m to the shortest path
Label the node m as reached
- Recompute the shortest paths of nodes that can be reached via m (if possible)
Again, no improvements.... (because there are no more unreached nodes !!!)
Result at the end of the iteration:
Done !!!
- Find the unreached node m that has the shortest path from the source node:
- Initilaization:
二. 算法伪代码
- Psuedo code of the Dijkstra's Algorithm:
/* ------------------------ Initialization ------------------------ */ ReachSet := {S} (Shortest path from S to all other nodes) for ( all other nodes n ≠ S ) do { D[n] = linkcost(S,n); // D[n] = length of shortest path S -> n if ( LinkCost[s][i] < infinite ) predNode[i] = S; // Record the "predecessor edge" to node n // This info. says: edge S -> n is used to go to n } /* ----------------------- Find min. cost path ----------------------- */ while ( ReachSet ≠ all nodes ) do { Find the node m ∈ (N - ReachSet) that has smallest value for D[m] /* ================================================ Label node m as "reached" ================================================ */ ReachSet := ReachSet ∪ {m} // shortest path to m has been found // We don't have to do anything to add the edge used to // get to m to the shortest path // The variable "predNode[m] kept track of this info ! /* --------------------------------------------------------------- Recompute the shortest paths of nodes that can be reached via m --------------------------------------------------------------- */ for ( each node n ∈ (N - ReachSet) ) do { /* ================================================================== How to discover possible better path to n via m: current shortest length = D[n] S <-------> n \ / \ / D[m] \ / linkcost(m,n) \ / \ / m We have a better shortest path is: D[m] + linkcost(m,n) < D[n] ================================================================== */ if ( D[m] + linkcost(m,n) < D[n] ) { D[n] = D[m] + linkcost(m,n); // Update the length predNode[n] = m; // Use m -> n to reach n ! } } }
三.Code in java
Dijkstra's Algorithm in Java:
public void Dijkstra(int s) // s = the source node
{
int i, j, m, n, k;
int[] D = new int[NNodes]; // Current distance
int[] predNode = new int[NNodes]; // shortest path edges
/* ==============================================
Initialize: ReachSet = {s}
UnReachSet = all other nodes
============================================== */
for ( i = 0; i < NNodes; i++ )
Reached[i] = false;
Reached[s] = true; // ReachSet = {s}
/* ========================================================
Use edge from the source node as the shortest path to
nodes that you can reach immediately
======================================================== */
predNode[s] = s;
for ( i = 0; i < NNodes; i++ )
{
D[i] = LinkCost[s][i]; // Min. distance
if ( LinkCost[s][i] < infinite )
predNode[i] = s; // edge of shortest path
}
/* ========================================================
The Dijkstra's Algorithm (need to loop NNodes-1 times)
======================================================== */
for ( k = 0; k < NNodes-1; k++ )
{
/* =============================================================
Find the first unreached node m
============================================================= */
for ( m = 0; m < NNodes; m++ )
if ( ! Reached[m] )
break;
/* =============================================================
Check if there is a unreached node with shorter path length
============================================================= */
for ( n = m+1; n < NNodes; n++ )
{
if ( Reached[n] == false && D[n] < D[m] )
m = n; // A better node is found, update m
}
// Now: m = unreach node with smallest value for D[m]
/* ==========================
Add m to ReachSet
========================== */
Reached[m] = true;
/* ------------------------------------------------------
Find possible "short cut" through m
(better shortest paths through m)
------------------------------------------------------ */
for ( n = 0; n < NNodes; n++ )
{
if ( Reached[n] == false )
{
if ( D[m] + LinkCost[m][n] < D[n] )
{
D[n] = D[m] + LinkCost[m][n]; // Shorter path found !
predNode[n] = m; // Record the shortest path link
}
}
}
}
} |
完整运行Code 参见:
http://www.mathcs.emory.edu/~cheung/Courses/171/Syllabus/11-Graph/Progs/Dijkstra
Output:
Shortest path from node B
A B C D E
--------------------
A * 5 10 * *
B 5 * 3 11 *
C 10 3 * 2 *
D * 11 2 * 3
E * * * 3 *
ReachSet = B --- initial state
D[A] = 5, D[C] = 3, D[D] = 11, D[E] = * --- add m = C
ReachSet = B C
D[A] = 5, D[D] = 5, D[E] = * --- add m = A
ReachSet = A B C
D[D] = 5, D[E] = * --- add m = D
ReachSet = A B C D
D[E] = 8 --- add m = E
ReachSet = A B C D E
Shortest paths:
B --> A
B --> B
B --> C
C --> D
D --> E
|
四.分析
1. 时间复杂度O(n²)
2. 适用于权值为非负的图单源(从一个节点到其它节点)最短路径查找
3. 如果求所有N个节点之间的最短路径,N个节点都要执行该算法。时间复杂度为O(n³)