Dijkstra's Algorithm
Dijkstra's Algorithm is one of the most famous and widely used algorithms in computer science and graph theory. It solves the single-source shortest path problem in a weighted graph. Developed by Edsger W. Dijkstra in 1956, this algorithm finds the shortest path between a starting node and all other nodes in a graph. It works on graphs with non-negative edge weights and is highly efficient for various real-world applications, including routing in networking, navigation systems, and optimization problems.
Given a weighted, directed graph with a starting node (also known as the source), Dijkstra's Algorithm finds the shortest path from the source node to all other nodes in the graph. It ensures that each node is visited in order of increasing distance from the source.
The algorithm maintains a set of visited nodes and iteratively explores the nearest unvisited node. The key idea is to use a greedy approach, where at each step, the node with the smallest known distance is selected for exploration. The algorithm updates the distances of the neighboring nodes, and once all nodes are visited, the shortest paths are found.
Initialization:
Selection of the Minimum Distance Node:
Update Neighboring Nodes:
Mark the Current Node as Visited:
Repeat:
Result:
Consider a graph with the following edges and weights:
2 3
A --------> B --------> C
| | |
| 1 | 4 | 5
| | |
v v v
D --------> E --------> F
6 1
Let's now look at how to implement Dijkstra's Algorithm in both Python and C++.
import heapq
def dijkstra(graph, start):
# Distance table: all nodes initially have infinite distance
distances = {node: float('inf') for node in graph}
distances[start] = 0
# Priority queue to explore the node with the smallest tentative distance
priority_queue = [(0, start)]
while priority_queue:
current_distance, current_node = heapq.heappop(priority_queue)
# If this distance is already greater than the recorded distance, skip it
if current_distance > distances[current_node]:
continue
# Explore neighbors
for neighbor, weight in graph[current_node]:
distance = current_distance + weight
# If a shorter path to the neighbor is found, update it
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(priority_queue, (distance, neighbor))
return distances
# Sample usage
graph = {
'A': [('B', 2), ('D', 1)],
'B': [('C', 3), ('E', 4)],
'C': [('F', 5)],
'D': [('E', 6)],
'E': [('F', 1)],
'F': []
}
start_node = 'A'
print(f"Shortest distances from {start_node}: {dijkstra(graph, start_node)}")
Explanation:
This Python implementation efficiently calculates the shortest distances from the source node to all other nodes in the graph.
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#include <unordered_map>
using namespace std;
typedef pair<int, int> pii;
void dijkstra(unordered_map<char, vector<pii>>& graph, char start) {
unordered_map<char, int> distances;
// Initialize distances
for (auto& pair : graph) {
distances[pair.first] = INT_MAX;
}
distances[start] = 0;
// Min-heap to pick the node with the smallest distance
priority_queue<pii, vector<pii>, greater<pii>> pq;
pq.push({0, start});
while (!pq.empty()) {
int current_distance = pq.top().first;
char current_node = pq.top().second;
pq.pop();
// Skip if the current distance is greater than the known shortest distance
if (current_distance > distances[current_node]) continue;
// Explore neighbors
for (auto& neighbor : graph[current_node]) {
char next_node = neighbor.first;
int weight = neighbor.second;
int new_distance = current_distance + weight;
// Update if a shorter path is found
if (new_distance < distances[next_node]) {
distances[next_node] = new_distance;
pq.push({new_distance, next_node});
}
}
}
// Print the results
for (auto& pair : distances) {
cout << "Distance from " << start << " to " << pair.first << " is " << pair.second << endl;
}
}
int main() {
unordered_map<char, vector<pii>> graph;
graph['A'] = {{'B', 2}, {'D', 1}};
graph['B'] = {{'C', 3}, {'E', 4}};
graph['C'] = {{'F', 5}};
graph['D'] = {{'E', 6}};
graph['E'] = {{'F', 1}};
graph['F'] = {};
char start = 'A';
dijkstra(graph, start);
return 0;
}
Explanation:
This C++ code works similarly to the Python version, calculating the shortest path from a start node to all other nodes in the graph.
Time Complexity: The time complexity of Dijkstra's Algorithm is O((V + E) log V), where:
If we use an adjacency matrix to represent the graph, the time complexity becomes O(V^2), but using an adjacency list with a priority queue makes it more efficient.
Space Complexity: The space complexity is O(V + E), as we need to store the graph and the distances of all vertices.
Dijkstra's Algorithm has wide applications in solving real-world problems: