1use core::marker::PhantomData;
4
5use crate::{
6 quickunion::Heuristic, rng::PhantomRng, AlgorithmContainer, Borrowed, Connected, Find, Owned,
7 Union, UnionFind, VertexType,
8};
9
10#[derive(Debug, Default)]
12pub struct QuickFind<K = Owned> {
13 _p: PhantomData<K>,
14}
15
16pub struct NoHeuristic;
17
18impl Heuristic for NoHeuristic {
19 type RngProvider = PhantomRng;
20
21 fn handle_decision<T>(
22 _a: T::IdentifierType,
23 _b: T::IdentifierType,
24 _heuristic: &mut [usize],
25 _representative: &mut [T],
26 _r: &mut Self::RngProvider,
27 ) where
28 T: VertexType,
29 {
30 unreachable!("Should not be called!")
31 }
32}
33
34impl AlgorithmContainer for QuickFind<Owned> {
35 type HeuristicKind<'a> = NoHeuristic;
36 type HeuristicContainer<'a, const N: usize> = [usize; 0];
37 type RepresentativeContainer<'a, R: VertexType + 'a, const N: usize> = [R; N];
38 type RngKind<'a> = PhantomRng;
39}
40
41impl AlgorithmContainer for QuickFind<Borrowed> {
42 type HeuristicKind<'a> = NoHeuristic;
43 type HeuristicContainer<'a, const N: usize> = [usize; 0];
44 type RepresentativeContainer<'a, R: VertexType + 'a, const N: usize> = &'a mut [R];
45 type RngKind<'a> = PhantomRng;
46}
47
48macro_rules! generate_default_ctor_quickfind {
49 ($($num_type:ident), *) => {
50 $(
51 impl<const N: usize> Default for UnionFind<'_, QuickFind, $num_type, N>
52 {
53 fn default() -> Self {
54 let mut representative = [0; N];
55
56 for i in 0..(N as $num_type) {
57 representative[i as usize] = i;
58 }
59
60 Self {
61 representative,
62 heuristic: [0; 0],
63 algorithm: Default::default(),
64 rng: PhantomRng
65 }
66 }
67 }
68 )*
69 };
70}
71
72impl<'a, T, const N: usize> UnionFind<'a, QuickFind<Borrowed>, T, N>
73where
74 T: VertexType,
75{
76 pub fn new(representative: &'a mut [T]) -> Self {
77 Self {
78 representative,
79 heuristic: [0; 0],
80 algorithm: Default::default(),
81 rng: PhantomRng,
82 }
83 }
84}
85
86impl<T, K> Connected<T> for QuickFind<K>
87where
88 T: VertexType,
89 Self: Find<T>,
90{
91 fn connected(representative: &mut [T], a: T::IdentifierType, b: T::IdentifierType) -> bool {
92 Self::find(representative, a) == Self::find(representative, b)
93 }
94}
95
96impl<T, K> Union<T, NoHeuristic> for QuickFind<K>
97where
98 T: VertexType,
99 Self: Find<T>,
100{
101 fn union_sets(
102 representative: &mut [T],
103 _heuristic: &mut [usize],
104 a: T::IdentifierType,
105 b: T::IdentifierType,
106 _r: &mut PhantomRng,
107 ) {
108 let root_a = Self::find(representative, a);
109 let root_b = Self::find(representative, b);
110 for item in representative {
111 if *item == root_a {
112 *item = root_b;
113 }
114 }
115 }
116}
117
118impl<T, K> Find<T> for QuickFind<K>
119where
120 T: VertexType,
121{
122 fn find(representative: &mut [T], a: T::IdentifierType) -> T {
123 assert!(T::usize(a) < representative.len());
124 representative[T::usize(a)]
125 }
126}
127
128generate_default_ctor_quickfind!(u8, u16, u32, u64, usize);
129
130#[cfg(test)]
131mod tests {
132 use crate::{rng::PhantomRng, tests::CityVertex, Borrowed, QuickFind, UnionFind};
133 use core::{mem, panic};
134
135 #[test]
136 fn test_qf() {
137 let mut uf = UnionFind::<QuickFind, u32, 10>::default();
138 uf.union_sets(4, 3);
139 uf.union_sets(3, 8);
140 uf.union_sets(6, 5);
141 uf.union_sets(9, 4);
142 assert!(uf.connected(3, 9));
143 }
144
145 #[test]
146 fn test_qf_slice() {
147 let mut representative = (0..10).collect::<heapless::Vec<_, 10>>();
148 let mut uf = UnionFind::<QuickFind<Borrowed>, u32, 10>::new(representative.as_mut());
149 uf.union_sets(4, 3);
150 uf.union_sets(3, 8);
151 uf.union_sets(6, 5);
152 uf.union_sets(9, 4);
153 assert!(uf.connected(3, 9));
154 }
155
156 impl<'a, const N: usize> TryFrom<[CityVertex<'a>; N]>
157 for UnionFind<'_, QuickFind, CityVertex<'a>, N>
158 {
159 type Error = &'static str;
160
161 fn try_from(cities: [CityVertex<'a>; N]) -> Result<Self, Self::Error> {
162 for id in 0..N {
163 if cities[id].id as usize != id {
164 return Err("Invalid cities id!");
165 }
166 }
167
168 Ok(Self {
169 representative: cities,
170 heuristic: [0; 0],
171 algorithm: Default::default(),
172 rng: PhantomRng,
173 })
174 }
175 }
176
177 #[test]
178 fn test_custom_type() {
179 let cities = [
180 CityVertex::new(0, "Zurich", 320),
181 CityVertex::new(1, "Munich", 210),
182 CityVertex::new(2, "Paris", 180),
183 CityVertex::new(3, "London", 190),
184 CityVertex::new(4, "Oslo", 250),
185 CityVertex::new(5, "Stockholm", 280),
186 CityVertex::new(6, "Helsinki", 280),
187 ];
188
189 let mut uf = UnionFind::<QuickFind, CityVertex<'static>, 7>::try_from(cities).unwrap();
190 uf.union_sets(4, 3);
191 uf.union_sets(3, 2);
192 uf.union_sets(6, 5);
193 assert!(uf.connected(4, 2));
194 assert!(uf.connected(6, 5));
195 }
196
197 #[test]
198 fn test_sz() {
199 assert_eq!(
200 mem::size_of::<[u32; 10]>(),
201 mem::size_of::<UnionFind::<'_, QuickFind, u32, 10>>()
202 );
203 assert_eq!(
204 mem::size_of::<&'_ [u32]>(),
205 mem::size_of::<UnionFind::<'_, QuickFind<Borrowed>, u32, 10>>()
206 );
207 assert_eq!(
208 mem::size_of::<[CityVertex<'_>; 10]>(),
209 mem::size_of::<UnionFind::<'_, QuickFind, CityVertex<'_>, 10>>()
210 );
211 }
212
213 #[test]
214 fn test_getter() {
215 let mut uf = UnionFind::<QuickFind, u32, 10>::default();
216 uf.union_sets(4, 3);
217 uf.union_sets(3, 8);
218 uf.union_sets(6, 5);
219 uf.union_sets(9, 4);
220 for _ in uf.heuristic() {
221 panic!("Should not even loop!");
222 }
223 }
224}