petgraph/
unionfind.rs

1//! `UnionFind<K>` is a disjoint-set data structure.
2
3use super::graph::IndexType;
4use std::cmp::Ordering;
5
6/// `UnionFind<K>` is a disjoint-set data structure. It tracks set membership of *n* elements
7/// indexed from *0* to *n - 1*. The scalar type is `K` which must be an unsigned integer type.
8///
9/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>
10///
11/// Too awesome not to quote:
12///
13/// “The amortized time per operation is **O(α(n))** where **α(n)** is the
14/// inverse of **f(x) = A(x, x)** with **A** being the extremely fast-growing Ackermann function.”
15#[derive(Debug, Clone)]
16pub struct UnionFind<K> {
17    // For element at index *i*, store the index of its parent; the representative itself
18    // stores its own index. This forms equivalence classes which are the disjoint sets, each
19    // with a unique representative.
20    parent: Vec<K>,
21    // It is a balancing tree structure,
22    // so the ranks are logarithmic in the size of the container -- a byte is more than enough.
23    //
24    // Rank is separated out both to save space and to save cache in when searching in the parent
25    // vector.
26    rank: Vec<u8>,
27}
28
29#[inline]
30unsafe fn get_unchecked<K>(xs: &[K], index: usize) -> &K {
31    debug_assert!(index < xs.len());
32    xs.get_unchecked(index)
33}
34
35#[inline]
36unsafe fn get_unchecked_mut<K>(xs: &mut [K], index: usize) -> &mut K {
37    debug_assert!(index < xs.len());
38    xs.get_unchecked_mut(index)
39}
40
41impl<K> UnionFind<K>
42where
43    K: IndexType,
44{
45    /// Create a new `UnionFind` of `n` disjoint sets.
46    pub fn new(n: usize) -> Self {
47        let rank = vec![0; n];
48        let parent = (0..n).map(K::new).collect::<Vec<K>>();
49
50        UnionFind { parent, rank }
51    }
52
53    /// Return the representative for `x`.
54    ///
55    /// **Panics** if `x` is out of bounds.
56    pub fn find(&self, x: K) -> K {
57        assert!(x.index() < self.parent.len());
58        unsafe {
59            let mut x = x;
60            loop {
61                // Use unchecked indexing because we can trust the internal set ids.
62                let xparent = *get_unchecked(&self.parent, x.index());
63                if xparent == x {
64                    break;
65                }
66                x = xparent;
67            }
68            x
69        }
70    }
71
72    /// Return the representative for `x`.
73    ///
74    /// Write back the found representative, flattening the internal
75    /// datastructure in the process and quicken future lookups.
76    ///
77    /// **Panics** if `x` is out of bounds.
78    pub fn find_mut(&mut self, x: K) -> K {
79        assert!(x.index() < self.parent.len());
80        unsafe { self.find_mut_recursive(x) }
81    }
82
83    unsafe fn find_mut_recursive(&mut self, mut x: K) -> K {
84        let mut parent = *get_unchecked(&self.parent, x.index());
85        while parent != x {
86            let grandparent = *get_unchecked(&self.parent, parent.index());
87            *get_unchecked_mut(&mut self.parent, x.index()) = grandparent;
88            x = parent;
89            parent = grandparent;
90        }
91        x
92    }
93
94    /// Returns `true` if the given elements belong to the same set, and returns
95    /// `false` otherwise.
96    pub fn equiv(&self, x: K, y: K) -> bool {
97        self.find(x) == self.find(y)
98    }
99
100    /// Unify the two sets containing `x` and `y`.
101    ///
102    /// Return `false` if the sets were already the same, `true` if they were unified.
103    ///
104    /// **Panics** if `x` or `y` is out of bounds.
105    pub fn union(&mut self, x: K, y: K) -> bool {
106        if x == y {
107            return false;
108        }
109        let xrep = self.find_mut(x);
110        let yrep = self.find_mut(y);
111
112        if xrep == yrep {
113            return false;
114        }
115
116        let xrepu = xrep.index();
117        let yrepu = yrep.index();
118        let xrank = self.rank[xrepu];
119        let yrank = self.rank[yrepu];
120
121        // The rank corresponds roughly to the depth of the treeset, so put the
122        // smaller set below the larger
123        match xrank.cmp(&yrank) {
124            Ordering::Less => self.parent[xrepu] = yrep,
125            Ordering::Greater => self.parent[yrepu] = xrep,
126            Ordering::Equal => {
127                self.parent[yrepu] = xrep;
128                self.rank[xrepu] += 1;
129            }
130        }
131        true
132    }
133
134    /// Return a vector mapping each element to its representative.
135    pub fn into_labeling(mut self) -> Vec<K> {
136        // write in the labeling of each element
137        unsafe {
138            for ix in 0..self.parent.len() {
139                let k = *get_unchecked(&self.parent, ix);
140                let xrep = self.find_mut_recursive(k);
141                *self.parent.get_unchecked_mut(ix) = xrep;
142            }
143        }
144        self.parent
145    }
146}