Shortest Path Algorithm - Dijkstra's Algorithm

090644t797fce7n20of7j9.png

 

       Like the Floyd-Warshall algorithm, the two-dimensional array e is still used to store the edge relationship between vertices. The initial values ​​are as follows.
090651l6pt4666tptut66u.png

 

       We also need to use a one-dimensional array dis to store the initial path from vertex 1 to the other vertices, as follows.
090657ofidcactthcig33i.png

 

       We call the value in the dis array at this point the shortest path "estimator".
       Since it is to find the shortest distance from vertex 1 to the other vertices, first find a vertex closest to vertex 1. Through the array dis, it can be known that the current closest vertex to vertex 1 is vertex 2. When vertex 2 is selected, the value of dis[2] has changed from "estimated value" to "determined value", that is, the shortest distance from vertex 1 to vertex 2 is the current dis[2] value. why? You think, the closest vertex to vertex 1 is vertex 2, and all the edges of this graph are positive numbers, so it is definitely impossible to transfer through the third vertex, which further shortens the distance from vertex 1 to vertex 2. . Because the distance from vertex 1 to other vertices is definitely not as short as vertex 1 to 2, right? O(∩_∩)O~
       Now that vertex 2 is selected, let's look at the outgoing edges of vertex 2. There are two sides 2->3 and 2->4. Let's first discuss whether the distance from vertex 1 to vertex 3 can be shortened by the edge 2->3. That is to say, now let's compare the size of dis[3] and dis[2]+e[2][3]. where dis[3] represents the distance from vertex 1 to vertex 3. In dis[2]+e[2][3], dis[2] represents the distance from vertex 1 to vertex 2, and e[2][3] represents the edge 2->3. So dis[2]+e[2][3] means the distance from vertex 1 to vertex 2, and then through the edge 2->3 to vertex 3.
       We find that dis[3]=12, dis[2]+e[2][3]=1+9=10, dis[3]>dis[2]+e[2][3], so dis[3 ] to update to 10. This process has a technical term called "relaxation". That is, the distance from vertex 1 to vertex 3 is dis[3], and the relaxation is successful through the edge 2->3. This is the main idea of ​​Dijkstra's algorithm: relax the path from vertex 1 to other vertices through "edges".
 
       Similarly, through 2->4 (e[2][4]), the value of dis[4] can be relaxed from ∞ to 4 (dis[4] is initially ∞, dis[2]+e[2][4 ]=1+3=4, dis[4]>dis[2]+e[2][4], so dis[4] should be updated to 4).
       Just now we relaxed all outgoing edges of vertex 2. After relaxation, the dis array is:
090706vmjy7l2ee2lyalia.png

 

       Next, continue to select the vertex closest to vertex 1 among the remaining vertices 3, 4, 5, and 6. By updating the dis array above, the current vertex 4 is closest to vertex 1. At this point, the value of dis[4] has changed from "estimated value" to "determined value". Next, continue to relax all outgoing edges (4->3, 4->5 and 4->6) of vertex 4 with the method just now. After relaxation, the dis array is:
090714f2p1wppynngj2pep.png

 

       Continue with the remaining vertices 3, 5, and 6 and pick the one closest to vertex 1, this time picking vertex 3. At this point, the value of dis[3] has changed from "estimated value" to "determined value". Relax all outgoing edges (3->5) of vertex 3. After relaxation, the dis array is:
090722ywunackk35i8cni5.png

 

       Continue with the remaining vertices 5 and 6, pick the vertex closest to vertex 1, this time select vertex 5. At this point, the value of dis[5] has changed from "estimated value" to "determined value". Relax all outgoing edges (5->4) of vertex 5. After relaxation, the dis array is:
090730eq6oqzyq7laqha9y.png

 

       Finally, relax all outgoing edges of vertex 6. Because vertex 6 has no outgoing edge in this example, it does not need to be processed. At this point, all the values ​​in the dis array have changed from "estimated values" to "determined values".
       The final dis array is as follows, which is the shortest path from vertex 1 to the other vertices.
090738azt5clcozl899ekt.png

 

       OK, now to summarize the algorithm just now. The basic idea of ​​the algorithm is: each time find a vertex closest to the source point (the source point in the above example is vertex 1), and then expand with this vertex as the center, and finally get the shortest path from the source point to all other points. The basic steps are as follows:
  • Divide all vertices into two parts: vertex set P with known shortest path and vertex set Q with unknown shortest path. Initially, there is only one vertex in the vertex set P with the shortest path known. We use a book[i] array here to record which points are in the set P. For example, for a vertex i, if book[i] is 1, it means that this vertex is in set P, and if book[i] is 0, it means that this vertex is in set Q.

  • Set the shortest path from the source point s to itself to 0, that is, dis=0. If there is a vertex i that can be reached directly from the source point, set dis[ i ] to e[s][ i ]. At the same time, set the shortest paths of all other vertices (that the source point cannot reach directly) to ∞.

  • Among all the vertices of the set Q, select a vertex u that is closest to the source point s (that is, the dis[u] is the smallest) and add it to the set P. And examine all the edges starting from point u, and relax each edge. For example, if there is an edge from u to v, then a path from s to v can be extended by adding the edge u->v to the end. The length of this path is dis[u]+e[u][v] . If this value is smaller than the currently known value of dis[v], we can replace the current value in dis[v] with the new value.

  • Repeat step 3, if the set Q is empty, the algorithm ends. The final value in the dis array is the shortest path from the source point to all vertices.

code show as below:

#include <iostream>
#include <cstring>

#define MAX 6
#define INF 0xFFFFFFFF


/*
 * Dijkstra shortest path.
 * That is, the shortest path from the "vertex" to every other vertex in the statistical graph.
 *
 * Parameter Description:
 * vMatrix -- adjacency matrix
 * apex -- start vertex. That is, calculate the shortest path from "vertex apex" to other vertices.
 * prePoint -- array of predecessor vertices. The value of prePoint[i] is the vertex located before "vertex i" among all the vertices experienced by the shortest path from "vertex apex" to "vertex i".
 * finalPointVal -- an array of lengths. dist[i] is the length of the shortest path from "vertex apex" to "vertex i".
 */
void dijkstra(unsigned int vMatrix[][MAX], int apex, unsigned int prePoint[], unsigned int finalPointVal[])
{    
    int i, k;
    unsigned int temp, min;
     int flag[MAX] = { 0 }; // flag[i]=1 indicates that the shortest path from "apex apex" to "vertex i" has been successfully obtained. 
    for ( int i= 0 ; i<MAX; i++ )
    {
        flag[i] = 0 ;         // The shortest path of vertex i has not been obtained yet. 
        prePoint[i] = 0 ;     // The predecessor vertex of vertex i is 0. 
        finalPointVal[i] = vMatrix[apex][i];     // The shortest path of vertex i is the weight from "vertex apex" to "vertex i". 
    }
    
    // Initialize "apex apex" itself 
    flag[apex] = 1 ;
    prePoint[apex] = 0;
    
    // Traverse, each time to find the shortest path to a vertex. 
    for (i= 1 ; i<MAX; i++ )
    {
        min = INF;
         for ( int j= 0 ; j<MAX; j++) // find the current smallest path, that is, the array finalPointVal, the fixed point of the smallest weight 
        {
             if (flag[j]== 0 && finalPointVal[j] < min)
            {
                min = finalPointVal [j];
                k = j;
            }
        }
        flag[k] = 1 ; // mark "vertex k" as having obtained the shortest path
        
        for ( int j= 0 ; j<MAX; j++) // correct the current shortest path and predecessor vertices, that is: after "the shortest path of vertex k", update "the shortest path and predecessor vertex of the vertex that does not obtain the shortest path" " 
        {
            temp = (vMatrix[k][j]==INF ? INF:(min+vMatrix[k][j]));
            if (flag[j]==0 && temp<finalPointVal[j])
            {
                finalPointVal [j] = temp;
                prePoint[j] = k;
            }
        }
    }
    
    for (i = 0; i < MAX; i++)
        std::cout << "shortest(1," << i+1 << ") = " << finalPointVal[i] << std::endl;
        
}


int main(int argc, char *argv[])
{
    unsigned int prePoint[MAX];
    unsigned int desPoint[MAX];
    unsigned int vMatrix[MAX][MAX] = {{0, 1, 12, INF, INF, INF},
                           {INF, 0 , 9 , 3 , INF, INF},
                           {INF, INF, 0 , INF, 5 , INF},
                           {INF, INF, 4 , 0 , 13 , 15 },
                           {INF, INF, INF, INF, 0 , 4 },
                           {INF, INF, INF, INF, INF, 0 }};
                           
    
    memset(prePoint, 0, sizeof(prePoint));
    memset(desPoint, 0, sizeof(desPoint));
    dijkstra(vMatrix, 0, prePoint, desPoint);
    return 0;
}

 

Reference blog: https://blog.csdn.net/heroacool/article/details/51014824

        http://blog.51cto.com/ahalei/1387799

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326292479&siteId=291194637