Implementation of Dijkstra Algorithm in C++

Dijkstra’s Algorithm is a classic greedy algorithm for finding the shortest path from a single source vertex to all other vertices in a weighted graph with non-negative edge weights. It maintains a set of visited vertices and a distance array. At each step it selects the unvisited vertex with the smallest known distance, marks it visited, and relaxes (updates) the distances of its neighbours. This process repeats until all vertices have been visited.

This C++ program reads a cost matrix from the user (entering -1 for absent edges and 0 for self-loops), runs Dijkstra’s algorithm from a user-specified source vertex, and prints the shortest distance and parent vertex for every node.

C++ Program: Dijkstra’s Shortest Path Algorithm

#include <iostream.h>
#include <conio.h>

void main()
{
    int rowIndex, colIndex;   // Loop counters for matrix traversal

    // --- Read the number of vertices ---
    int vertexCount;
    cout << "\n Enter vertex count: ";
    cin >> vertexCount;

    // --- Initialise the cost matrix to -1 (no edge) ---
    int costMatrix[15][15];
    for (rowIndex = 0; rowIndex < vertexCount; rowIndex++)
    {
        for (colIndex = 0; colIndex < vertexCount; colIndex++)
        {
            costMatrix[rowIndex][colIndex] = -1;
        }
    }

    // --- Read edge weights from the user ---
    // Self-loops are set to 0; for each pair (u,v) with u != v,
    // the user enters the edge weight or -1 for no direct connection.
    cout << "\n Enter weight of edges:\n";
    for (rowIndex = 0; rowIndex < vertexCount; rowIndex++)
    {
        for (colIndex = 0; colIndex < vertexCount; colIndex++)
        {
            if (rowIndex == colIndex)
                costMatrix[rowIndex][colIndex] = 0;   // Distance from a vertex to itself is 0

            if (costMatrix[rowIndex][colIndex] == -1) // Only prompt for unfilled entries
            {
                cout << "\n " << rowIndex << " to " << colIndex << " : ";
                cin >> costMatrix[rowIndex][colIndex];
            }
        }
    }

    // --- Display the cost matrix ---
    cout << "\n Entered Cost Matrix:";
    cout << "\n";
    for (rowIndex = 0; rowIndex < vertexCount; rowIndex++)
    {
        for (colIndex = 0; colIndex < vertexCount; colIndex++)
        {
            cout << costMatrix[rowIndex][colIndex] << " ";
        }
        cout << "\n";
    }

    // --- Initialise Dijkstra data structures ---
    int shortestDist[15];   // shortestDist[v] = best known distance from source to v
    int parentVertex[15];   // parentVertex[v] = predecessor of v on the shortest path
    int visited[15];        // visited[v] = 1 once v has been finalised

    for (rowIndex = 0; rowIndex < vertexCount; rowIndex++)
    {
        shortestDist[rowIndex] = 999;    // Infinity
        parentVertex[rowIndex] = -1;     // No parent yet
        visited[rowIndex]      = 0;      // Not yet visited
    }

    // --- Read the source vertex ---
    int sourceVertex;
    cout << "\n Enter Starting vertex: ";
    cin >> sourceVertex;

    // Distance from source to itself is 0
    shortestDist[sourceVertex] = 0;
    parentVertex[sourceVertex] = -1;
    visited[sourceVertex]      = 1;

    int currentVertex = sourceVertex;   // Vertex being processed in the current iteration
    int smallestDist  = 999;            // Tracks the minimum distance among unvisited vertices

    // --- Main Dijkstra loop: repeat (vertexCount - 1) times ---
    for (rowIndex = 0; rowIndex < vertexCount - 1; rowIndex++)
    {
        // Relax all neighbours of currentVertex
        for (colIndex = 0; colIndex < vertexCount; colIndex++)
        {
            if (costMatrix[currentVertex][colIndex] > 0)  // Edge exists
            {
                if (shortestDist[colIndex] > shortestDist[currentVertex] + costMatrix[currentVertex][colIndex])
                {
                    shortestDist[colIndex] = shortestDist[currentVertex] + costMatrix[currentVertex][colIndex];
                    parentVertex[colIndex] = currentVertex;
                }
            }
        }

        // Mark currentVertex as visited
        visited[currentVertex] = 1;
        smallestDist = 999;

        // Pick the unvisited vertex with the smallest known distance
        for (int scanIndex = 0; scanIndex < vertexCount; scanIndex++)
        {
            if (visited[scanIndex] != 1 && shortestDist[scanIndex] < smallestDist)
            {
                smallestDist  = shortestDist[scanIndex];
                currentVertex = scanIndex;
            }
        }

        smallestDist = 999;  // Reset for next iteration
    }

    // --- Display the shortest path table ---
    cout << "\n Shortest Path:";
    cout << "\n Vertex\tDist\tParent\n";
    for (rowIndex = 0; rowIndex < vertexCount; rowIndex++)
    {
        cout << rowIndex << "\t" << shortestDist[rowIndex] << "\t" << parentVertex[rowIndex] << "\n";
    }

    getch();
}

How the Code Works

Step 1 — Input: The user enters the number of vertices and the weight of each edge. Entering -1 means no direct edge; entering 0 is automatically set for self-loops.

Step 2 — Initialisation: All distances are set to 999 (representing infinity) and all vertices are marked unvisited. The source vertex distance is set to 0 and it is immediately marked visited.

Step 3 — Relaxation: For the current vertex, every adjacent vertex is checked. If the path through the current vertex is shorter than the previously known distance, the distance and parent are updated.

Step 4 — Next Vertex Selection: After relaxation, the algorithm scans all unvisited vertices and selects the one with the smallest distance as the next current vertex. This greedy choice guarantees that each vertex is finalised with its true shortest distance.

Step 5 — Repeat: Steps 3 and 4 repeat for vertexCount - 1 iterations, after which all reachable vertices have their final shortest distances.

Step 6 — Output: The program prints a table showing each vertex, its shortest distance from the source, and its parent vertex on the shortest path. A parent of -1 means the vertex is the source (or unreachable).

Sample Output


 Enter vertex count: 5

 Enter weight of edges:

 0 to 1 : 10

 0 to 2 : -1

 0 to 3 : 5

 0 to 4 : -1

 1 to 0 : -1

 1 to 2 : 1

 1 to 3 : 2

 1 to 4 : -1

 2 to 0 : -1

 2 to 1 : -1

 2 to 3 : -1

 2 to 4 : 4

 3 to 0 : -1

 3 to 1 : 3

 3 to 2 : 9

 3 to 4 : 2

 4 to 0 : -1

 4 to 1 : -1

 4 to 2 : 6

 4 to 3 : -1

 Entered Cost Matrix:
0 10 -1 5 -1
-1 0 1 2 -1
-1 -1 0 -1 4
-1 3 9 0 2
-1 -1 6 -1 0

 Enter Starting vertex: 0

 Shortest Path:
 Vertex  Dist    Parent
0       0       -1
1       8       3
2       9       1
3       5       0
4       7       3

Output Explanation

Starting from vertex 0, the algorithm explores all 5 vertices. The direct edge 0→3 costs 5, so vertex 3 is reached first. From vertex 3, the path 0→3→1 costs 8 (cheaper than the direct edge 0→1 = 10), so vertex 1’s distance is updated to 8 with parent 3. Continuing, vertex 4 is reached via 0→3→4 at cost 7, and vertex 2 is reached via 0→3→1→2 at cost 9. The final table reflects these optimal routes.

See Also

Conclusion

Dijkstra’s algorithm is the foundation of many real-world routing protocols, including OSPF (Open Shortest Path First) used in IP networks. Its greedy approach guarantees optimal shortest paths in graphs with non-negative weights, and the cost matrix model used in this program maps directly to how network topologies are represented in practice. Extending this implementation with a priority queue (min-heap) would reduce the time complexity from O(V²) to O((V + E) log V) for sparse graphs.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.