Skip to content

Commit 6f2a72c

Browse files
Add Kruskal's MST algorithm (#265)
1 parent 9954b50 commit 6f2a72c

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Kruskal's Minimum Spanning Tree (MST) Algorithm
2+
#
3+
# Kruskal's algorithm finds a subset of edges that connects all vertices in a graph
4+
# without any cycles and with the minimum possible total edge weight.
5+
#
6+
# It uses the Disjoint Set Union (DSU) or Union-Find data structure to detect cycles efficiently.
7+
#
8+
# Time Complexity: O(E log E) — dominated by sorting edges
9+
# Space Complexity: O(V)
10+
#
11+
# Input: graph as a list of edges (each edge has `u`, `v`, and `weight`)
12+
# Output: List containing MST edges and total minimum cost
13+
14+
# -------------------------
15+
# Helper: Disjoint Set (Union-Find)
16+
# -------------------------
17+
18+
make_set <- function(n) {
19+
parent <- 1:n
20+
rank <- rep(0, n)
21+
return(list(parent = parent, rank = rank))
22+
}
23+
24+
find_set <- function(parent, v) {
25+
if (parent[v] != v) {
26+
parent[v] <- find_set(parent, parent[v]) # Path compression
27+
}
28+
return(parent[v])
29+
}
30+
31+
union_sets <- function(parent, rank, a, b) {
32+
a_root <- find_set(parent, a)
33+
b_root <- find_set(parent, b)
34+
35+
if (a_root != b_root) {
36+
if (rank[a_root] < rank[b_root]) {
37+
temp <- a_root
38+
a_root <- b_root
39+
b_root <- temp
40+
}
41+
parent[b_root] <- a_root
42+
if (rank[a_root] == rank[b_root]) {
43+
rank[a_root] <- rank[a_root] + 1
44+
}
45+
}
46+
return(list(parent = parent, rank = rank))
47+
}
48+
49+
# -------------------------
50+
# Kruskal's MST Algorithm
51+
# -------------------------
52+
53+
kruskal_mst <- function(edges, num_vertices) {
54+
# Sort edges by weight
55+
edges <- edges[order(sapply(edges, function(e) e$weight))]
56+
57+
# Initialize disjoint sets
58+
dsu <- make_set(num_vertices)
59+
parent <- dsu$parent
60+
rank <- dsu$rank
61+
62+
mst_edges <- list()
63+
total_cost <- 0
64+
65+
# Process each edge
66+
for (edge in edges) {
67+
u <- edge$u
68+
v <- edge$v
69+
w <- edge$weight
70+
71+
u_root <- find_set(parent, u)
72+
v_root <- find_set(parent, v)
73+
74+
# If u and v are in different sets, include this edge
75+
if (u_root != v_root) {
76+
mst_edges <- append(mst_edges, list(edge))
77+
total_cost <- total_cost + w
78+
merged <- union_sets(parent, rank, u_root, v_root)
79+
parent <- merged$parent
80+
rank <- merged$rank
81+
}
82+
}
83+
84+
return(list(
85+
mst_edges = mst_edges,
86+
total_cost = total_cost
87+
))
88+
}
89+
90+
# -------------------------
91+
# Example usage and testing
92+
# -------------------------
93+
94+
cat("=== Kruskal's Minimum Spanning Tree Algorithm ===\n")
95+
96+
# Example undirected weighted graph (edges list)
97+
# Graph:
98+
# 1 --(4)-- 2
99+
# 1 --(3)-- 3
100+
# 2 --(1)-- 3
101+
# 2 --(2)-- 4
102+
# 3 --(5)-- 4
103+
edges <- list(
104+
list(u = 1, v = 2, weight = 4),
105+
list(u = 1, v = 3, weight = 3),
106+
list(u = 2, v = 3, weight = 1),
107+
list(u = 2, v = 4, weight = 2),
108+
list(u = 3, v = 4, weight = 5)
109+
)
110+
111+
cat("Graph edges:\n")
112+
for (e in edges) {
113+
cat(paste0("(", e$u, " -- ", e$v, ") weight = ", e$weight, "\n"))
114+
}
115+
116+
cat("\nRunning Kruskal's MST:\n")
117+
result <- kruskal_mst(edges, num_vertices = 4)
118+
119+
cat("MST Edges:\n")
120+
for (e in result$mst_edges) {
121+
cat(paste0("(", e$u, " -- ", e$v, ") weight = ", e$weight, "\n"))
122+
}
123+
124+
cat("Total Minimum Cost:", result$total_cost, "\n")

0 commit comments

Comments
 (0)