Understanding Dijkstra’s Algorithm: A Comprehensive Guide with Implementation in C

Dive into Dijkstra's Algorithm with this detailed guide. Learn its logic, pseudo code, and C implementation step-by-step.

Understanding Dijkstra’s Algorithm: A Comprehensive Guide with Implementation in C
Photo by GeoJango Maps / Unsplash

Introduction

Dijkstra’s Algorithm is a fundamental concept in computer science and graph theory, widely used for finding the shortest path between nodes in a graph. Named after Dutch computer scientist Edsger W. Dijkstra, this algorithm has become a staple in various applications such as GPS navigation systems, network routing protocols, and even in game development for pathfinding. In this blog, we will explore the intricacies of Dijkstra’s Algorithm, provide a step-by-step breakdown of its logic, present the pseudo code, and walk you through its implementation in C. By the end of this article, you will have a solid understanding of how Dijkstra's Algorithm works and how to implement it in your projects.

Algorithm Details

Step-by-Step Explanation

Dijkstra's Algorithm operates by iteratively selecting the node with the smallest known distance, updating its neighbors with the shortest discovered distance, and repeating this process until all nodes have been processed. Here's a detailed step-by-step breakdown of the algorithm:

  1. Initialization: Start with a graph, where each node has an associated cost (initially set to infinity, except for the starting node which is set to zero). Create a priority queue to store nodes based on their current cost.
  2. Select Node: Extract the node with the smallest cost from the priority queue.
  3. Update Neighbors: For each neighbor of the selected node, calculate the tentative cost from the start node to the neighbor through the current node. If this cost is less than the previously known cost, update the cost and set the current node as the predecessor of the neighbor.
  4. Repeat: Repeat steps 2 and 3 until the priority queue is empty or the destination node is reached.
  5. Construct Path: Once the algorithm completes, the shortest path can be reconstructed by tracing back from the destination node using the predecessor information.

Pseudo Code

function Dijkstra(Graph, source):
    dist[source] ← 0
    create priority queue Q
    for each vertex v in Graph:
        if v ≠ source:
            dist[v] ← ∞
        add v to Q
    while Q is not empty:
        u ← vertex in Q with min dist[u]
        remove u from Q
        for each neighbor v of u:
            alt ← dist[u] + length(u, v)
            if alt < dist[v]:
                dist[v] ← alt
                previous[v] ← u
    return dist[], previous[]

Implementation in C

Here’s a detailed implementation of Dijkstra’s Algorithm in C:

Code

#include <stdio.h>
#include <limits.h>
#include <stdbool.h>

#define V 9

int minDistance(int dist[], bool sptSet[]) {
    int min = INT_MAX, min_index;

    for (int v = 0; v < V; v++)
        if (sptSet[v] == false && dist[v] <= min)
            min = dist[v], min_index = v;

    return min_index;
}

void printSolution(int dist[]) {
    printf("Vertex \t Distance from Source\n");
    for (int i = 0; i < V; i++)
        printf("%d \t\t %d\n", i, dist[i]);
}

void dijkstra(int graph[V][V], int src) {
    int dist[V];
    bool sptSet[V];

    for (int i = 0; i < V; i++)
        dist[i] = INT_MAX, sptSet[i] = false;

    dist[src] = 0;

    for (int count = 0; count < V - 1; count++) {
        int u = minDistance(dist, sptSet);
        sptSet[u] = true;

        for (int v = 0; v < V; v++)
            if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v])
                dist[v] = dist[u] + graph[u][v];
    }

    printSolution(dist);
}

int main() {
    int graph[V][V] = {{0, 4, 0, 0, 0, 0, 0, 8, 0},
                       {4, 0, 8, 0, 0, 0, 0, 11, 0},
                       {0, 8, 0, 7, 0, 4, 0, 0, 2},
                       {0, 0, 7, 0, 9, 14, 0, 0, 0},
                       {0, 0, 0, 9, 0, 10, 0, 0, 0},
                       {0, 0, 4, 14, 10, 0, 2, 0, 0},
                       {0, 0, 0, 0, 0, 2, 0, 1, 6},
                       {8, 11, 0, 0, 0, 0, 1, 0, 7},
                       {0, 0, 2, 0, 0, 0, 6, 7, 0}};
    
    dijkstra(graph, 0);

    return 0;
}

Explanation of C Code

  1. Graph Representation: The graph is represented as a 2D array graph[V][V], where V is the number of vertices.
  2. Distance Array: dist[] holds the shortest distance from the source to each vertex.
  3. Shortest Path Tree Set (sptSet): sptSet[] keeps track of vertices included in the shortest path tree.
  4. minDistance Function: This function returns the vertex with the minimum distance value, from the set of vertices not yet processed.
  5. dijkstra Function: This is the core function where Dijkstra’s Algorithm is implemented.
  6. printSolution Function: This function prints the shortest distance from the source to all vertices.

Time and Space Complexity

Time Complexity

The time complexity of Dijkstra's Algorithm varies depending on the implementation:

  • Using a simple array: O(V2)O(V^2)O(V2), where VVV is the number of vertices.
  • Using a priority queue (min-heap): O((V+E)log⁡V)O((V + E) \log V)O((V+E)logV), where EEE is the number of edges. This is the more efficient implementation and is commonly used.

Space Complexity

The space complexity is O(V)O(V)O(V) for storing the distance array and shortest path tree set. If adjacency lists are used to represent the graph, the space complexity is O(V+E)O(V + E)O(V+E).

Usage

Dijkstra’s Algorithm has a wide range of applications:

  • GPS Navigation Systems: To find the shortest path between two locations.
  • Network Routing Protocols: To find the shortest path for data packets in a network.
  • Robotics and AI: For pathfinding in robots and game development.
  • Telecommunications: To optimize routing and network design.

Conclusion

Dijkstra’s Algorithm is a powerful and efficient method for finding the shortest path in a graph. By understanding its step-by-step logic and implementing it in C, you can leverage this algorithm in various applications. Its importance in both theoretical and practical aspects of computer science makes it a crucial tool for any programmer's toolkit.

If you found this blog helpful or have any suggestions for improving it, please leave your feedback or suggestions in the comments. Your input is valuable in helping me create better and more informative content for you!

Subscribe to rahulv.dev | blog

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
[email protected]
Subscribe