Day 45: Kruskal's Algorithm
Table of Contents
Kruskal’s Algorithm #
Welcome to Day 45 of our 60 Days of Coding Algorithm Challenge! Today, we’ll explore Kruskal’s Algorithm, another greedy algorithm used for finding the Minimum Spanning Tree (MST) of a weighted undirected graph.
What is Kruskal’s Algorithm? #
Kruskal’s Algorithm is a minimum-spanning-tree algorithm which finds an edge of the least possible weight that connects any two trees in the forest. It is a greedy algorithm in graph theory as it finds a minimum spanning tree for a connected weighted graph adding increasing cost arcs at each step.
How Kruskal’s Algorithm Works #
- Sort all the edges from low weight to high.
- Take the edge with the lowest weight and add it to the spanning tree. If adding the edge created a cycle, then reject this edge.
- Keep adding edges until we reach all vertices.
Implementation #
Let’s implement Kruskal’s Algorithm in Python:
class DisjointSet:
def __init__(self, vertices):
self.parent = {v: v for v in vertices}
self.rank = {v: 0 for v in vertices}
def find(self, item):
if self.parent[item] != item:
self.parent[item] = self.find(self.parent[item])
return self.parent[item]
def union(self, x, y):
xroot = self.find(x)
yroot = self.find(y)
if self.rank[xroot] < self.rank[yroot]:
self.parent[xroot] = yroot
elif self.rank[xroot] > self.rank[yroot]:
self.parent[yroot] = xroot
else:
self.parent[yroot] = xroot
self.rank[xroot] += 1
def kruskal(graph):
edges = [(cost, u, v) for u in graph for v, cost in graph[u].items()]
edges.sort()
vertices = list(graph.keys())
ds = DisjointSet(vertices)
mst = []
for cost, u, v in edges:
if ds.find(u) != ds.find(v):
ds.union(u, v)
mst.append((u, v, cost))
return mst
# Example usage
graph = {
'A': {'B': 2, 'C': 3},
'B': {'A': 2, 'C': 1, 'D': 1, 'E': 4},
'C': {'A': 3, 'B': 1, 'F': 5},
'D': {'B': 1, 'E': 1},
'E': {'B': 4, 'D': 1, 'F': 1},
'F': {'C': 5, 'E': 1}
}
minimum_spanning_tree = kruskal(graph)
print("Edges in the Minimum Spanning Tree:")
for u, v, cost in minimum_spanning_tree:
print(f"{u} -- {v}: {cost}")
Time Complexity #
The time complexity of Kruskal’s algorithm is O(E log E) or O(E log V), where E is the number of edges and V is the number of vertices. This is because:
- Sorting the edges takes O(E log E) time.
- The disjoint-set operations (find and union) take O(log V) time per operation.
Space Complexity #
O(V), where V is the number of vertices in the graph, for the disjoint-set data structure.
Advantages of Kruskal’s Algorithm #
- Efficient for sparse graphs
- Easy to implement
- Can be used to find Maximum Spanning Trees by negating edge weights
Comparison with Prim’s Algorithm #
- Kruskal’s algorithm is generally faster for sparse graphs.
- Prim’s algorithm is generally faster for dense graphs.
- Kruskal’s builds the MST by adding edges, while Prim’s builds it by adding vertices.
Applications #
- Network design (e.g., designing a least-cost network)
- Clustering algorithms
- Approximation algorithms for NP-hard problems (e.g., traveling salesman problem)
- Image segmentation in computer vision
Exercise #
- Implement Kruskal’s algorithm using an edge list representation instead of an adjacency list.
- Modify the algorithm to find the Maximum Spanning Tree instead of the Minimum Spanning Tree.
- Implement a function that compares the MSTs generated by Prim’s and Kruskal’s algorithms for the same graph.
Summary #
Today, we explored Kruskal’s Algorithm, another fundamental graph algorithm for finding Minimum Spanning Trees. We implemented the algorithm, discussed its time and space complexity, and looked at its advantages and applications.
Understanding Kruskal’s Algorithm, along with Prim’s Algorithm from yesterday, provides a comprehensive toolkit for solving problems related to Minimum Spanning Trees and network optimization.
Tomorrow, we’ll dive into another important graph algorithm: the Floyd-Warshall Algorithm. Stay tuned!