Dijkstra’s Shortest Path Algorithm

Single-source shortest path algorithm for graphs with non-negative edge weights.


Context

Dijkstra’s algorithm computes the shortest path from a single source to all other vertices in a graph with:

If negative edges exist → this algorithm is incorrect. Use Bellman–Ford instead.

Time complexity depends on implementation:


Core idea

Dijkstra is greedy. At every step:

Key invariant:

Once a vertex is marked visited, its shortest distance is final.

That works only because weights are non-negative.


Implementation

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import java.util.Collections;

class DijkstraShortestPath {
    List<Integer> find(GraphEdge[][] graph, int source, int target) {
        var n = graph.length;
        
        var visited = new boolean[n];
        
        var distances = new int[n];
        Arrays.fill(distances, Integer.MAX_VALUE);
        distances[source] = 0;
        
        var prev = new int[n];
        Arrays.fill(prev, -1);
        
        while(hasUnvisited(visited, distances)) {
            var lo = getLowestUnvisited(visited, distances);
            visited[lo] = true;
            
            for (var edge : graph[lo]) {
                if (!visited[edge.to]) {
                    var distance = distances[lo] + edge.weight;
                    if (distances[edge.to] > distance) {
                        distances[edge.to] = distance;
                        prev[edge.to] = lo;
                    }
                }
            }
        }
        
        if (prev[target] == -1 && target != source) return List.of();
        
        List<Integer> out = new ArrayList<>();
        for (var at = target; at != -1; at = prev[at]) {
            out.add(at);
        }
        
        Collections.reverse(out);
        return out;
    }
    
    private boolean hasUnvisited(boolean[] visited, int[] distances) {
        return IntStream.range(0, visited.length)
            .anyMatch(i -> !visited[i] && distances[i] != Integer.MAX_VALUE);
    }
    
    private int getLowestUnvisited(boolean[] visited, int[] distances) {
        var minIndex = -1;
        var minValue = Integer.MAX_VALUE;
        
        for (var i = 0; i < visited.length; i++) {
            if (!visited[i] && distances[i] < minValue) {
                minIndex = i;
                minValue = distances[i];
            }
        }
        
        return minIndex;
    }
    
    record GraphEdge(int to, int weight) {}
}