Kruskal Algorithm
Palavras-chave:
Publicado em: 31/08/2025Kruskal's Algorithm: Finding the Minimum Spanning Tree
Kruskal's algorithm is a greedy algorithm used to find the Minimum Spanning Tree (MST) for a weighted, undirected graph. An MST connects all vertices in the graph with the minimum possible total edge weight, without forming any cycles. This article provides a detailed explanation and implementation of Kruskal's algorithm.
Fundamental Concepts / Prerequisites
To understand Kruskal's algorithm, familiarity with the following concepts is helpful:
- Graph Theory: Understanding of graphs, vertices, edges, weighted graphs, and spanning trees.
- Greedy Algorithms: The basic principle of making locally optimal choices at each step to find a global optimum.
- Disjoint Set Data Structure (Union-Find): A data structure that keeps track of a set of elements partitioned into a number of disjoint (non-overlapping) subsets. It supports efficient operations for finding which subset an element belongs to and merging subsets together.
Core Implementation
The following C++ code implements Kruskal's algorithm using the Disjoint Set data structure.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Structure to represent an edge
struct Edge {
int src, dest, weight;
};
// Structure to represent a Disjoint Set (Union-Find)
struct DisjointSets {
int *parent, *rnk;
int n;
// Constructor
DisjointSets(int n) {
this->n = n;
parent = new int[n+1];
rnk = new int[n+1];
// Initially, all vertices are in different sets
for (int i = 0; i <= n; i++) {
rnk[i] = 0;
parent[i] = i;
}
}
// Find the parent of a node (path compression)
int find(int u) {
if (u != parent[u])
parent[u] = find(parent[u]); // Path compression
return parent[u];
}
// Union by rank
void unite(int x, int y) {
x = find(x);
y = find(y);
if (rnk[x] > rnk[y])
parent[y] = x;
else
parent[x] = y;
if (rnk[x] == rnk[y])
rnk[y]++;
}
};
// Function to compare edges based on weight
bool compareEdges(const Edge& a, const Edge& b) {
return a.weight < b.weight;
}
// Kruskal's algorithm implementation
int kruskalMST(vector<Edge>& edges, int numVertices) {
int mstWeight = 0; // Weight of the MST
// Sort edges in ascending order by weight
sort(edges.begin(), edges.end(), compareEdges);
// Create DisjointSets data structure
DisjointSets ds(numVertices);
// Iterate through the sorted edges
for (const Edge& edge : edges) {
int src = edge.src;
int dest = edge.dest;
int weight = edge.weight;
// If including this edge doesn't cause a cycle, include it in MST
if (ds.find(src) != ds.find(dest)) {
mstWeight += weight;
ds.unite(src, dest);
}
}
return mstWeight;
}
int main() {
int numVertices = 4;
vector<Edge> edges = {
{0, 1, 10},
{0, 2, 6},
{0, 3, 5},
{1, 3, 15},
{2, 3, 4}
};
int mstWeight = kruskalMST(edges, numVertices);
cout << "Weight of the Minimum Spanning Tree: " << mstWeight << endl;
return 0;
}
Code Explanation
The code consists of the following parts:
Edge Structure: Represents an edge in the graph, containing the source vertex (src
), destination vertex (dest
), and the edge weight (weight
).
DisjointSets Structure: Implements the Union-Find data structure. parent
array stores the parent of each node in its set. rnk
array stores the rank (approximate height) of each tree in the forest. find()
finds the representative (root) of the set an element belongs to, and utilizes path compression for optimization. unite()
merges two sets together using union by rank, which helps keep the trees relatively flat, resulting in faster find operations.
compareEdges Function: A comparison function used to sort the edges in ascending order based on their weights.
kruskalMST Function:
- Initializes the MST weight to 0.
- Sorts the edges in ascending order of their weights using the
compareEdges
function. - Creates a
DisjointSets
object to track connected components. - Iterates through the sorted edges. For each edge:
- If adding the edge does not create a cycle (checked using
ds.find(src) != ds.find(dest)
), the edge is added to the MST. - The weight of the edge is added to the
mstWeight
. - The two vertices connected by the edge are merged into the same set using
ds.unite(src, dest)
.
- If adding the edge does not create a cycle (checked using
- Returns the total weight of the MST.
main Function: Creates a sample graph with edges and their weights. Calls kruskalMST()
to compute and print the MST's weight.
Complexity Analysis
Time Complexity:
- Sorting the edges: O(E log E), where E is the number of edges.
- Iterating through the edges: O(E).
- For each edge, performing
find
andunite
operations using Disjoint Sets: Almost O(1) on average, due to path compression and union by rank. More precisely, it's O(α(V)), where α is the very slowly growing inverse Ackermann function, and V is the number of vertices. For all practical purposes, α(V) is considered a constant (less than 5 for any realistically sized graph).
Therefore, the overall time complexity is dominated by the sorting step: O(E log E). Since E can be at most V2, O(E log E) is the same as O(E log V).
Space Complexity:
- Storing the edges: O(E).
- Disjoint Sets data structure (parent and rank arrays): O(V).
Therefore, the overall space complexity is O(E + V).
Alternative Approaches
Prim's Algorithm: Another greedy algorithm for finding the MST. It starts with a single vertex and iteratively adds the minimum-weight edge that connects the current tree to a new vertex. Prim's algorithm generally performs better (especially with dense graphs) when implemented using a binary heap or Fibonacci heap. Its time complexity is O(E log V) with a binary heap and O(E + V log V) with a Fibonacci heap. The main difference from Kruskal's is that Prim's algorithm builds the MST from a single vertex, always maintaining a connected tree, while Kruskal's considers edges in increasing order of weight, possibly building several disconnected trees until the end.
Conclusion
Kruskal's algorithm provides an efficient and intuitive way to find the Minimum Spanning Tree of a graph. It leverages the Disjoint Set data structure to efficiently detect and avoid cycles. Understanding Kruskal's algorithm is fundamental for solving various network optimization problems.