Shortest path algorithms in Javascript

In graph theory, the shortest path problem is finding a path between two vertices in a graph such that the sum of edge weights is minimized. To implement shortest path algorithms, we need to modify our graph structure to support weighted edges.

Setting Up Weighted Graphs

First, let's modify our graph methods to handle weights:

class WeightedGraph {
    constructor() {
        this.nodes = [];
        this.edges = {};
    }
    
    addNode(node) {
        this.nodes.push(node);
        this.edges[node] = [];
    }
    
    // Adds bidirectional edge with weight
    addEdge(node1, node2, weight = 1) {
        this.edges[node1].push({ node: node2, weight: weight });
        this.edges[node2].push({ node: node1, weight: weight });
    }
    
    // Adds directional edge with weight
    addDirectedEdge(node1, node2, weight = 1) {
        this.edges[node1].push({ node: node2, weight: weight });
    }
    
    display() {
        this.nodes.forEach(node => {
            const connections = this.edges[node]
                .map(edge => `${edge.node}(${edge.weight})`)
                .join(", ");
            console.log(`${node} -> ${connections}`);
        });
    }
}

// Create and test weighted graph
const graph = new WeightedGraph();
graph.addNode('A');
graph.addNode('B');
graph.addNode('C');
graph.addEdge('A', 'B', 4);
graph.addEdge('B', 'C', 2);
graph.addEdge('A', 'C', 5);
graph.display();
A -> B(4), C(5)
B -> A(4), C(2)
C -> B(2), A(5)

Dijkstra's Algorithm Implementation

Dijkstra's algorithm finds the shortest path from a source node to all other nodes:

class WeightedGraph {
    constructor() {
        this.nodes = [];
        this.edges = {};
    }
    
    addNode(node) {
        this.nodes.push(node);
        this.edges[node] = [];
    }
    
    addEdge(node1, node2, weight = 1) {
        this.edges[node1].push({ node: node2, weight: weight });
        this.edges[node2].push({ node: node1, weight: weight });
    }
    
    dijkstra(start) {
        const distances = {};
        const previous = {};
        const unvisited = new Set();
        
        // Initialize distances
        this.nodes.forEach(node => {
            distances[node] = node === start ? 0 : Infinity;
            previous[node] = null;
            unvisited.add(node);
        });
        
        while (unvisited.size > 0) {
            // Find unvisited node with minimum distance
            let current = null;
            for (let node of unvisited) {
                if (current === null || distances[node] < distances[current]) {
                    current = node;
                }
            }
            
            unvisited.delete(current);
            
            // Update distances to neighbors
            this.edges[current].forEach(neighbor => {
                const newDistance = distances[current] + neighbor.weight;
                if (newDistance < distances[neighbor.node]) {
                    distances[neighbor.node] = newDistance;
                    previous[neighbor.node] = current;
                }
            });
        }
        
        return { distances, previous };
    }
    
    getShortestPath(start, end) {
        const { distances, previous } = this.dijkstra(start);
        const path = [];
        let current = end;
        
        while (current !== null) {
            path.unshift(current);
            current = previous[current];
        }
        
        return {
            path: path,
            distance: distances[end]
        };
    }
}

// Example usage
const graph = new WeightedGraph();
['A', 'B', 'C', 'D'].forEach(node => graph.addNode(node));

graph.addEdge('A', 'B', 1);
graph.addEdge('A', 'C', 4);
graph.addEdge('B', 'C', 2);
graph.addEdge('B', 'D', 5);
graph.addEdge('C', 'D', 1);

const result = graph.getShortestPath('A', 'D');
console.log(`Shortest path from A to D: ${result.path.join(' -> ')}`);
console.log(`Total distance: ${result.distance}`);
Shortest path from A to D: A -> B -> C -> D
Total distance: 4

Floyd-Warshall Algorithm

The Floyd-Warshall algorithm finds shortest paths between all pairs of nodes:

function floydWarshall(graph) {
    const nodes = graph.nodes;
    const n = nodes.length;
    const dist = {};
    
    // Initialize distance matrix
    nodes.forEach(i => {
        dist[i] = {};
        nodes.forEach(j => {
            if (i === j) {
                dist[i][j] = 0;
            } else {
                dist[i][j] = Infinity;
            }
        });
    });
    
    // Set direct edge distances
    nodes.forEach(node => {
        graph.edges[node].forEach(edge => {
            dist[node][edge.node] = edge.weight;
        });
    });
    
    // Floyd-Warshall main algorithm
    nodes.forEach(k => {
        nodes.forEach(i => {
            nodes.forEach(j => {
                if (dist[i][k] + dist[k][j] < dist[i][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            });
        });
    });
    
    return dist;
}

// Test Floyd-Warshall
const graph2 = new WeightedGraph();
['A', 'B', 'C'].forEach(node => graph2.addNode(node));
graph2.addEdge('A', 'B', 3);
graph2.addEdge('B', 'C', 1);
graph2.addEdge('A', 'C', 10);

const allPaths = floydWarshall(graph2);
console.log('All shortest distances:');
console.log('A to B:', allPaths['A']['B']);
console.log('A to C:', allPaths['A']['C']);
console.log('B to C:', allPaths['B']['C']);
All shortest distances:
A to B: 3
A to C: 4
B to C: 1

Comparison of Algorithms

Algorithm Time Complexity Use Case Handles Negative Weights
Dijkstra's O(V² + E) Single source, all destinations No
Floyd-Warshall O(V³) All pairs shortest paths Yes (no negative cycles)

Conclusion

Shortest path algorithms are essential for navigation, network routing, and optimization problems. Dijkstra's algorithm is ideal for single-source scenarios, while Floyd-Warshall works for all-pairs shortest paths with support for negative weights.

Updated on: 2026-03-15T23:18:59+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements