Boruvka's Algorithm
Boruvka's Algorithm is a greedy algorithm used to find the minimum spanning tree (MST) of a connected, undirected graph. The algorithm works by merging the components of the graph and selecting the minimum-weight edges that connect these components. Boruvka's Algorithm was one of the earliest algorithms to find the MST.
How Boruvka's Algorithm Works
-
Initialization:
- Start with each vertex as a separate component in the forest of the MST.
-
Phase 1: Components and Minimum Edges:
- For each component, select the minimum-weight edge incident to each component.
- Merge the components connected by these selected edges.
-
Repeat Merging:
- Repeat the phase until there's only one component left.
-
Completion:
- The final one-component graph is the Minimum Spanning Tree.
Key Features
-
Greedy Approach: Boruvka's Algorithm makes locally optimal choices to build a globally optimal solution.
-
Minimum Spanning Tree: It finds the MST, ensuring the least possible total edge weight to connect all vertices.
Efficiency
-
Time Complexity: The time complexity of Boruvka's Algorithm is O(E log V), where E is the number of edges and V is the number of vertices.
-
Space Complexity: The space complexity depends on the data structures used. In the worst case, it can be O(E + V).
Applications
-
Network Design: Boruvka's Algorithm is used in network design for laying down minimum-length electrical wires or connecting a set of houses with minimal cost.
-
Clustering: It can be applied in clustering problems, like partitioning data points into clusters while minimizing the total inter-cluster distance.
-
MST Construction: Boruvka's Algorithm is used to find MSTs in various applications, including computer networks and geographic information systems.
Limitations
-
Sensitivity to Edge Weights: The algorithm's performance can vary based on the choice of edge weights. Different edge weight assignments can result in different minimum spanning trees.
-
Must Be Connected: Boruvka's Algorithm requires the graph to be connected. If the graph has disconnected components, it needs to be run separately on each component.
-
High Time Complexity: While relatively efficient, Boruvka's Algorithm might not be the best choice for extremely large graphs.
Boruvka's Algorithm Implementation in JavaScript
Here's an example of Boruvka's Algorithm implemented in JavaScript:
class Graph {
constructor() {
this.vertices = [];
this.edges = [];
}
addVertex(vertex) {
this.vertices.push(vertex);
}
addEdge(vertex1, vertex2, weight) {
this.edges.push({ vertex1, vertex2, weight });
}
boruvkaMST() {
const mst = [];
let numVertices = this.vertices.length;
while (numVertices > 1) {
let closestEdges = Array(numVertices).fill(null);
for (const edge of this.edges) {
const root1 = this.findRoot(edge.vertex1);
const root2 = this.findRoot(edge.vertex2);
if (root1 !== root2) {
if (closestEdges[root1] === null || edge.weight < closestEdges[root1].weight) {
closestEdges[root1] = edge;
}
if (closestEdges[root2] === null || edge.weight < closestEdges[root2].weight) {
closestEdges[root2] = edge;
}
}
}
for (let i = 0; i < numVertices; i++) {
if (closestEdges[i] !== null) {
const root1 = this.findRoot(closestEdges[i].vertex1);
const root2 = this.findRoot(closestEdges[i].vertex2);
if (root1 !== root2) {
mst.push(closestEdges[i]);
this.union(root1, root2);
numVertices--;
}
}
}
}
return mst;
}
findRoot(vertex) {
if (this.vertices.includes(vertex)) return vertex;
return this.findRoot(this.vertices[vertex]);
}
union(root1, root2) {
this.vertices[root2] = root1;
}
}
// Example usage
const graph = new Graph();
const vertices = ["A", "B", "C", "D", "E"];
vertices.forEach((vertex) => graph.addVertex(vertex));
graph.addEdge("A", "B", 2);
graph.addEdge("A", "C", 3);
graph.addEdge("B", "C", 1);
graph.addEdge("B", "D", 1);
graph.addEdge("C", "D", 1);
graph.addEdge("C", "E", 4);
graph.addEdge("D", "E", 2);
const mst = graph.boruvkaMST();
console.log("Minimum Spanning Tree (MST):", mst);