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
Selected Reading
Complete Graph Class in Javascript
This article presents a comprehensive Graph class implementation in JavaScript with various graph algorithms including traversal, shortest path, and minimum spanning tree algorithms.
Graph Class Structure
The Graph class uses an adjacency list representation with two main properties:
-
nodes- Array storing all graph vertices -
edges- Object mapping each node to its connected neighbors with weights
Basic Graph Operations
const Queue = require("./Queue");
const Stack = require("./Stack");
const PriorityQueue = require("./PriorityQueue");
class Graph {
constructor() {
this.edges = {};
this.nodes = [];
}
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 });
}
addDirectedEdge(node1, node2, weight = 1) {
this.edges[node1].push({ node: node2, weight: weight });
}
display() {
let graph = "";
this.nodes.forEach(node => {
graph += node + "->" + this.edges[node].map(n => n.node).join(", ") + "<br>";
});
console.log(graph);
}
}
Graph Traversal Algorithms
Breadth-First Search (BFS)
BFS(node) {
let q = new Queue(this.nodes.length);
let explored = new Set();
q.enqueue(node);
explored.add(node);
while (!q.isEmpty()) {
let t = q.dequeue();
console.log(t);
this.edges[t].filter(n => !explored.has(n.node)).forEach(n => {
explored.add(n.node);
q.enqueue(n.node);
});
}
}
Depth-First Search (DFS)
DFS(node) {
let s = new Stack(this.nodes.length);
let explored = new Set();
s.push(node);
explored.add(node);
while (!s.isEmpty()) {
let t = s.pop();
console.log(t);
this.edges[t].filter(n => !explored.has(n.node)).forEach(n => {
explored.add(n.node);
s.push(n.node);
});
}
}
Shortest Path Algorithms
BFS Shortest Path (Unweighted)
BFSShortestPath(n1, n2) {
let q = new Queue(this.nodes.length);
let explored = new Set();
let distances = {};
distances[n1] = 0;
q.enqueue(n1);
explored.add(n1);
while (!q.isEmpty()) {
let t = q.dequeue();
this.edges[t].filter(n => !explored.has(n.node)).forEach(n => {
explored.add(n.node);
distances[n.node] = distances[t] + 1;
q.enqueue(n.node);
});
}
return distances[n2];
}
Dijkstra's Algorithm (Weighted)
dijkstraAlgorithm(startNode) {
let distances = {};
let prev = {};
let pq = new PriorityQueue(this.nodes.length * this.nodes.length);
distances[startNode] = 0;
pq.enqueue(startNode, 0);
this.nodes.forEach(node => {
if (node !== startNode) distances[node] = Infinity;
prev[node] = null;
});
while (!pq.isEmpty()) {
let minNode = pq.dequeue();
let currNode = minNode.data;
this.edges[currNode].forEach(neighbor => {
let alt = distances[currNode] + neighbor.weight;
if (alt < distances[neighbor.node]) {
distances[neighbor.node] = alt;
prev[neighbor.node] = currNode;
pq.enqueue(neighbor.node, distances[neighbor.node]);
}
});
}
return distances;
}
Minimum Spanning Tree Algorithms
Prim's Algorithm
primsMST() {
const MST = new Graph();
if (this.nodes.length === 0) {
return MST;
}
let s = this.nodes[0];
let edgeQueue = new PriorityQueue(this.nodes.length * this.nodes.length);
let explored = new Set();
explored.add(s);
MST.addNode(s);
this.edges[s].forEach(edge => {
edgeQueue.enqueue([s, edge.node], edge.weight);
});
while (!edgeQueue.isEmpty()) {
let currentMinEdge = edgeQueue.dequeue();
while (!edgeQueue.isEmpty() && explored.has(currentMinEdge.data[1])) {
currentMinEdge = edgeQueue.dequeue();
}
let nextNode = currentMinEdge.data[1];
if (!explored.has(nextNode)) {
MST.addNode(nextNode);
MST.addEdge(currentMinEdge.data[0], nextNode, currentMinEdge.priority);
this.edges[nextNode].forEach(edge => {
edgeQueue.enqueue([nextNode, edge.node], edge.weight);
});
explored.add(nextNode);
}
}
return MST;
}
Union-Find Data Structure
The UnionFind class supports Kruskal's MST algorithm by efficiently tracking connected components:
class UnionFind {
constructor(elements) {
this.count = elements.length;
this.parent = {};
elements.forEach(e => (this.parent[e] = e));
}
union(a, b) {
let rootA = this.find(a);
let rootB = this.find(b);
if (rootA === rootB) return;
if (rootA < rootB) {
if (this.parent[b] != b) this.union(this.parent[b], a);
this.parent[b] = this.parent[a];
} else {
if (this.parent[a] != a) this.union(this.parent[a], b);
this.parent[a] = this.parent[b];
}
}
find(a) {
while (this.parent[a] !== a) {
a = this.parent[a];
}
return a;
}
connected(a, b) {
return this.find(a) === this.find(b);
}
}
Algorithm Comparison
| Algorithm | Purpose | Time Complexity | Best For |
|---|---|---|---|
| BFS | Traversal/Shortest Path | O(V + E) | Unweighted graphs |
| DFS | Traversal | O(V + E) | Topological sorting |
| Dijkstra | Shortest Path | O((V + E) log V) | Weighted graphs |
| Prim's MST | Minimum Spanning Tree | O(E log V) | Dense graphs |
| Kruskal's MST | Minimum Spanning Tree | O(E log E) | Sparse graphs |
Conclusion
This comprehensive Graph class provides essential algorithms for graph traversal, shortest path finding, and minimum spanning tree construction. The implementation uses efficient data structures and follows standard algorithmic approaches for optimal performance in various graph operations.
Advertisements
