1. 程式人生 > >圖解-迪傑斯特拉演算法(找最短路徑)Dijkstra's Algorithm (finding shortestpaths)

圖解-迪傑斯特拉演算法(找最短路徑)Dijkstra's Algorithm (finding shortestpaths)

轉自: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:

       

       

     


     

  • 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:

       

       



       

    • 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)

         


         

      • 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:

       

       



       

    • 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:

       

       



       

    • 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 !!!

 

二. 演算法虛擬碼

  • 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³)