Your Progress
80% complete. Continue learning to master DSA!
Minimum Spanning Tree Algorithms
Minimum Spanning Tree (MST) algorithms find the subset of edges in a connected, undirected graph that connects all vertices with the minimum possible total edge weight, forming a tree without cycles.
Key Takeaways
- A Minimum Spanning Tree connects all vertices in a graph with the minimum total edge weight
- Kruskal's algorithm builds an MST by adding the next smallest edge that doesn't create a cycle
- Prim's algorithm grows an MST by adding the nearest vertex to the current tree
- Both algorithms are greedy approaches that always find the optimal solution
- MST algorithms have applications in network design, clustering, and approximation algorithms
What is a Minimum Spanning Tree?
A Spanning Tree of a connected, undirected graph is a subgraph that includes all vertices of the original graph and forms a tree (a connected graph without cycles). A Minimum Spanning Tree (MST) is a spanning tree with the minimum possible total edge weight.
Key Properties of MSTs
- Contains exactly n-1 edges for a graph with n vertices
- Forms a tree (connected and acyclic)
- Minimizes the total weight of all edges
- A graph may have multiple MSTs if there are edges with equal weights
- Every vertex is reachable from any other vertex in the MST
Example Graph and Its MST
Original Graph: Minimum Spanning Tree: A --- 2 --- B A --- 2 --- B |\ /| | | | \ / | | | 4| \6 3/ |5 4| |5 | \ / | | | | \ / | | | C --- 1 --- D C --- 1 --- D Total weight: 2 + 4 + 1 + 5 = 12
In this example, the MST includes the edges (A-B), (A-C), (C-D), and (B-D) with weights 2, 4, 1, and 5 respectively, giving a total weight of 12.
Kruskal's Algorithm
Kruskal's algorithm builds an MST by adding edges in order of increasing weight, skipping edges that would create a cycle. It uses a disjoint-set (union-find) data structure to efficiently detect cycles.
Algorithm Steps
- Sort all edges in non-decreasing order of weight
- Initialize a disjoint-set data structure with each vertex in its own set
- Iterate through the sorted edges:
- If including the current edge doesn't form a cycle (i.e., the endpoints are in different sets), add it to the MST
- Union the sets containing the endpoints of the included edge
- Continue until n-1 edges have been added to the MST
Implementation
class DisjointSet { constructor(n) { this.parent = Array(n).fill().map((_, i) => i); this.rank = Array(n).fill(0); } find(x) { if (this.parent[x] !== x) { this.parent[x] = this.find(this.parent[x]); // Path compression } return this.parent[x]; } union(x, y) { const rootX = this.find(x); const rootY = this.find(y); if (rootX === rootY) return false; // Union by rank if (this.rank[rootX] < this.rank[rootY]) { this.parent[rootX] = rootY; } else if (this.rank[rootX] > this.rank[rootY]) { this.parent[rootY] = rootX; } else { this.parent[rootY] = rootX; this.rank[rootX]++; } return true; } } function kruskalMST(graph) { const vertices = graph.vertices; const edges = graph.edges; // Sort edges by weight edges.sort((a, b) => a.weight - b.weight); const disjointSet = new DisjointSet(vertices.length); const mst = []; for (const edge of edges) { const { src, dest, weight } = edge; // Check if adding this edge creates a cycle if (disjointSet.union(src, dest)) { mst.push(edge); // Break early if we have n-1 edges (a spanning tree) if (mst.length === vertices.length - 1) break; } } return mst; }
Step-by-Step Example
Using our example graph with vertices A(0), B(1), C(2), D(3) and edges:
Edges sorted by weight: (C-D, 1), (A-B, 2), (B-D, 3), (A-C, 4), (B-C, 5), (A-D, 6) Steps: 1. Take edge (C-D, 1): Add to MST, union sets {C} and {D} MST = {(C-D, 1)}, Sets = {A}, {B}, {C,D} 2. Take edge (A-B, 2): Add to MST, union sets {A} and {B} MST = {(C-D, 1), (A-B, 2)}, Sets = {A,B}, {C,D} 3. Take edge (B-D, 3): Add to MST, union sets {A,B} and {C,D} MST = {(C-D, 1), (A-B, 2), (B-D, 3)}, Sets = {A,B,C,D} 4. We have n-1 = 3 edges, so the algorithm terminates Final MST = {(C-D, 1), (A-B, 2), (B-D, 3)} with total weight 6
Prim's Algorithm
Prim's algorithm builds an MST by starting from a single vertex and gradually growing the tree. It always adds the edge with the minimum weight that connects a vertex in the tree to a vertex outside the tree.
Algorithm Steps
- Start with any vertex as the initial MST
- Maintain two sets: vertices in the MST and vertices not yet included
- Maintain a priority queue of edges connecting the MST to vertices outside the MST
- In each step:
- Select the edge with minimum weight that connects a vertex in the MST to a vertex outside
- Add the selected edge to the MST and the new vertex to the MST set
- Update the priority queue with new edges from the newly added vertex
- Continue until all vertices are included in the MST
Implementation
function primMST(graph) { const vertices = graph.vertices.length; const adjList = graph.adjList; // Track vertices included in MST const inMST = Array(vertices).fill(false); // Key values used to pick minimum weight edge const key = Array(vertices).fill(Infinity); // Parent array to store MST const parent = Array(vertices).fill(-1); // Start with first vertex key[0] = 0; for (let count = 0; count < vertices - 1; count++) { // Pick the minimum key vertex not yet included in MST const u = minKey(key, inMST, vertices); // Add the picked vertex to the MST inMST[u] = true; // Update key and parent of adjacent vertices for (const [v, weight] of adjList[u]) { if (!inMST[v] && weight < key[v]) { parent[v] = u; key[v] = weight; } } } // Construct MST from parent array const mst = []; for (let i = 1; i < vertices; i++) { mst.push({ src: parent[i], dest: i, weight: key[i] }); } return mst; } function minKey(key, inMST, vertices) { let min = Infinity, minIndex = -1; for (let v = 0; v < vertices; v++) { if (!inMST[v] && key[v] < min) { min = key[v]; minIndex = v; } } return minIndex; }
Step-by-Step Example
Using our example graph with vertices A(0), B(1), C(2), D(3), starting from vertex A:
Initial: MST = {A}, Not in MST = {B, C, D} Key values: A=0, B=∞, C=∞, D=∞ Step 1: Examine edges from A: (A-B, 2), (A-C, 4), (A-D, 6) Update keys: B=2, C=4, D=6 Select B (minimum key not in MST) MST = {A, B}, Not in MST = {C, D} Key values: A=0, B=2, C=4, D=6 Step 2: Examine edges from B: (B-C, 5), (B-D, 3) Update keys: C=4 (unchanged), D=3 (improved) Select D (minimum key not in MST) MST = {A, B, D}, Not in MST = {C} Key values: A=0, B=2, C=4, D=3 Step 3: Examine edges from D: (D-C, 1) Update keys: C=1 (improved) Select C (minimum key not in MST) MST = {A, B, C, D}, Not in MST = {} Key values: A=0, B=2, C=1, D=3 Final MST = {(A-B, 2), (B-D, 3), (D-C, 1)} with total weight 6
Kruskal's vs. Prim's Algorithm
Aspect | Kruskal's Algorithm | Prim's Algorithm |
---|---|---|
Approach | Edge-based, processes edges in order of weight | Vertex-based, grows a single tree from a starting vertex |
Time Complexity | O(E log E) or O(E log V) | O(E log V) with binary heap, O(V²) with array |
Space Complexity | O(E + V) | O(V) |
Better For | Sparse graphs (E ≈ V) | Dense graphs (E ≈ V²) |
Data Structure | Disjoint-set (Union-Find) | Priority Queue (or min-heap) |
Both algorithms always find the correct MST, but their performance characteristics make them suitable for different types of graphs. The choice between them depends on the specific problem and graph structure.
Applications of Minimum Spanning Trees
Network Design
MSTs are used to design minimum cost networks, such as:
- Telecommunications networks
- Electrical grids
- Water supply networks
- Computer networks
Clustering
MSTs can be used in clustering algorithms:
- Single-linkage clustering
- Identifying clusters by removing the heaviest edges from the MST
- Hierarchical clustering based on MST distances
Approximation Algorithms
MSTs help approximate solutions to NP-hard problems:
- Traveling Salesman Problem (TSP)
- Steiner Tree Problem
- Minimum k-Connected Subgraph
Image Processing
Applications in computer vision and image analysis:
- Image segmentation
- Feature extraction
- Object recognition
Time and Space Complexity
Kruskal's Algorithm
Time complexity breakdown:
- Sorting edges: O(E log E)
- Processing each edge: O(E α(V))
- Overall: O(E log E) or O(E log V) since E can be at most V²
Space complexity: O(E + V) for storing the graph and disjoint-set data structure.
Prim's Algorithm
Time complexity depends on the implementation:
- Array implementation: O(V²)
- Binary heap implementation: O(E log V)
- Fibonacci heap implementation: O(E + V log V)
Space complexity: O(V) for storing the MST set, key values, and parent array.
Conclusion
Minimum Spanning Tree algorithms provide efficient solutions for finding the minimum-weight connected subgraph that includes all vertices. Both Kruskal's and Prim's algorithms use greedy approaches to construct MSTs and have their own advantages depending on the graph structure.
Remember
When working with MST problems:
- Use Kruskal's algorithm for sparse graphs (fewer edges)
- Use Prim's algorithm for dense graphs (many edges)
- Both algorithms always find the optimal solution
- Consider the implementation of disjoint-set or priority queue for performance optimization
Next Steps
To further your understanding of graph algorithms and MSTs, explore these related topics:
Related Tutorials
Related Tutorials
Graphs
Understand the foundation of graph theory needed for MST algorithms.
Learn moreGreedy Algorithms
Learn about the greedy approach used in MST algorithms.
Learn moreShortest Path Algorithms
Compare MST algorithms with path-finding algorithms.
Learn more