geop_core_math/
union_find.rs1#[derive(Clone, Debug)]
6pub struct UnionFind {
7 parent: Vec<usize>,
8}
9
10impl UnionFind {
11 pub fn new(n: usize) -> Self {
13 Self {
14 parent: (0..n).collect(),
15 }
16 }
17
18 pub fn find(&mut self, i: usize) -> usize {
20 let mut root = i;
21 while self.parent[root] != root {
22 root = self.parent[root];
23 }
24 let mut at = i;
25 while self.parent[at] != root {
26 at = std::mem::replace(&mut self.parent[at], root);
27 }
28 root
29 }
30
31 pub fn union(&mut self, a: usize, b: usize) {
33 let (a, b) = (self.find(a), self.find(b));
34 if a != b {
35 self.parent[a.max(b)] = a.min(b);
36 }
37 }
38
39 pub fn groups(&mut self) -> Vec<Vec<usize>> {
42 let mut by_root: std::collections::BTreeMap<usize, Vec<usize>> = Default::default();
43 for i in 0..self.parent.len() {
44 let root = self.find(i);
45 by_root.entry(root).or_default().push(i);
46 }
47 let mut groups: Vec<Vec<usize>> = by_root.into_values().collect();
48 groups.sort_by_key(|g| g[0]);
49 groups
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::UnionFind;
56
57 #[test]
58 fn groups_follow_unions() {
59 let mut sets = UnionFind::new(6);
60 sets.union(4, 1);
61 sets.union(2, 5);
62 sets.union(5, 4);
63 assert_eq!(sets.groups(), vec![vec![0], vec![1, 2, 4, 5], vec![3]]);
64 assert_eq!(sets.find(2), sets.find(1));
65 }
66}