Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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.
