Add Kruskal's minimum spanning tree algorithm

This commit is contained in:
Mikolaj Wielgus 2026-03-19 19:50:50 +01:00
parent a4d13a3435
commit f351728762
2 changed files with 49 additions and 0 deletions

View File

@ -14,8 +14,10 @@ dearcut = { version = "0.3", features = ["serde", "undoredo"] }
derive-getters.workspace = true
derive_more.workspace = true
i_triangle = "0.40"
polygon_unionfind = "0.5"
rstar = "0.12"
serde.workspace = true
spade = "2.15"
specctra = { path = "../specctra" }
stable-vec = "0.4"
undoredo.workspace = true

View File

@ -168,3 +168,50 @@ impl_polygon_centroid!(f32);
impl_polygon_centroid!(f64);
impl_polygon_centroid!(i32);
impl_polygon_centroid!(i64);
/// Kruskal's minimum spanning tree algorithm.
pub fn kruskal_mst<W: Copy + Ord>(
vertex_count: usize,
edges: &[(W, [usize; 2])],
) -> Vec<[usize; 2]> {
let mut sorted_edges = edges.to_vec();
sorted_edges.sort_by_key(|(w, _)| *w);
let mut unionfind: polygon_unionfind::UnionFind<Vec<usize>, Vec<usize>> =
polygon_unionfind::UnionFind::with_len(vertex_count);
let mut min_spanning_tree = Vec::new();
for (_, uv) in sorted_edges {
if unionfind.union(uv[0], uv[1]) {
min_spanning_tree.push(uv);
}
}
min_spanning_tree
}
#[cfg(test)]
mod tests {
use super::kruskal_mst;
#[test]
fn kruskal_mst_on_path_graph() {
// Path graph. Graph edges just form a sequence without cycle.
let edges = [(1, [0, 1]), (2, [1, 2]), (3, [2, 3])];
let mst = kruskal_mst(4, &edges);
assert_eq!(mst.len(), 3);
assert_eq!(mst, [[0, 1], [1, 2], [2, 3]]);
}
#[test]
fn kruskal_mst_on_triangle() {
// Triangle graph. Graph edges form a triangle.
let edges = [(1, [0, 1]), (2, [1, 2]), (3, [0, 2])];
let mst = kruskal_mst(3, &edges);
assert_eq!(mst.len(), 2);
assert!(mst.contains(&[0, 1]));
assert!(mst.contains(&[1, 2]));
}
}