From ddb070a69b84781c426b8a69fe8b5427a142263b Mon Sep 17 00:00:00 2001 From: tachsin Date: Sat, 12 Sep 2026 11:22:32 +0300 Subject: [PATCH] fix(prim): export from the prelude, and say what the two MST functions do when the graph is disconnected prim was the only algorithm not re-exported from the prelude, so `use pathfinding::prelude::*` reached kruskal but not prim, and callers had to name pathfinding::undirected::prim::prim in full. The two also disagree on disconnected input without saying so. prim grows outwards from one node and spans only that component; kruskal spans every component and returns a forest. Both simply said "minimum-spanning-tree", which is true of neither in that case without qualification. Document the difference on both, with a runnable example. --- src/lib.rs | 1 + src/undirected/kruskal.rs | 5 +++++ src/undirected/prim.rs | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 95dfc73c..dc18500c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,6 +150,7 @@ pub mod prelude { pub use crate::undirected::cliques::*; pub use crate::undirected::connected_components::*; pub use crate::undirected::kruskal::*; + pub use crate::undirected::prim::*; pub use crate::utils::*; } diff --git a/src/undirected/kruskal.rs b/src/undirected/kruskal.rs index ea9bb536..8ba924f4 100644 --- a/src/undirected/kruskal.rs +++ b/src/undirected/kruskal.rs @@ -56,6 +56,11 @@ where /// Find a minimum-spanning-tree. From a collection of /// weighted edges, return an iterator of edges forming /// a minimum-spanning-tree. +/// +/// # Disconnected graphs +/// +/// Every component is spanned, so the result is a spanning forest rather than a single tree. +/// [`prim`](super::prim::prim) differs here, and spans only the component it starts from. pub fn kruskal(edges: &[(N, N, C)]) -> impl Iterator where N: Hash + Eq, diff --git a/src/undirected/prim.rs b/src/undirected/prim.rs index 9aa87b71..5f1588da 100644 --- a/src/undirected/prim.rs +++ b/src/undirected/prim.rs @@ -11,6 +11,25 @@ use std::hash::Hash; /// /// Edges are undirected: `(a, b, c)` and `(b, a, c)` describe the same edge, and either form /// may be used. The tree is grown from the first endpoint of the first edge. +/// +/// # Disconnected graphs +/// +/// The tree is grown outwards from one node, so only the component containing that node is +/// spanned; edges in any other component are not returned. [`kruskal`](super::kruskal::kruskal) +/// differs here, and returns a spanning forest covering every component. +/// +/// ``` +/// use pathfinding::prelude::{kruskal, prim}; +/// +/// // Two components: 1-2 and 3-4. +/// let edges = vec![(1, 2, 1), (3, 4, 1)]; +/// +/// // prim spans the component holding node 1, the first endpoint of the first edge. +/// assert_eq!(prim(&edges), vec![(&1, &2, 1)]); +/// +/// // kruskal spans both. +/// assert_eq!(kruskal(&edges).count(), 2); +/// ``` pub fn prim(edges: &[(N, N, C)]) -> Vec<(&N, &N, C)> where N: Hash + Eq + Ord,