bhc_data_structures/
lib.rs1#![warn(missing_docs)]
7
8use rustc_hash::FxHasher;
9use std::hash::BuildHasherDefault;
10
11pub type FxHashMap<K, V> = std::collections::HashMap<K, V, BuildHasherDefault<FxHasher>>;
13
14pub type FxHashSet<T> = std::collections::HashSet<T, BuildHasherDefault<FxHasher>>;
16
17pub type FxIndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>;
19
20pub type FxIndexSet<T> = indexmap::IndexSet<T, BuildHasherDefault<FxHasher>>;
22
23pub use indexmap::{IndexMap, IndexSet};
25pub use parking_lot::{Mutex, RwLock};
26pub use smallvec::SmallVec;
27
28pub type TinyVec<T> = SmallVec<[T; 4]>;
30
31pub type SmallVec8<T> = SmallVec<[T; 8]>;
33
34pub trait FxHashMapExt<K, V> {
36 fn new() -> Self;
38 fn with_capacity(capacity: usize) -> Self;
40}
41
42impl<K, V> FxHashMapExt<K, V> for FxHashMap<K, V> {
43 fn new() -> Self {
44 Self::default()
45 }
46
47 fn with_capacity(capacity: usize) -> Self {
48 Self::with_capacity_and_hasher(capacity, BuildHasherDefault::default())
49 }
50}
51
52pub trait FxHashSetExt<T> {
54 fn new() -> Self;
56 fn with_capacity(capacity: usize) -> Self;
58}
59
60impl<T> FxHashSetExt<T> for FxHashSet<T> {
61 fn new() -> Self {
62 Self::default()
63 }
64
65 fn with_capacity(capacity: usize) -> Self {
66 Self::with_capacity_and_hasher(capacity, BuildHasherDefault::default())
67 }
68}
69
70#[derive(Debug, Clone)]
72pub struct WorkQueue<T> {
73 queue: std::collections::VecDeque<T>,
74 seen: FxHashSet<T>,
75}
76
77impl<T: std::hash::Hash + Eq + Clone> WorkQueue<T> {
78 #[must_use]
80 pub fn new() -> Self {
81 Self {
82 queue: std::collections::VecDeque::new(),
83 seen: FxHashSet::default(),
84 }
85 }
86
87 pub fn push(&mut self, item: T) -> bool {
89 if self.seen.insert(item.clone()) {
90 self.queue.push_back(item);
91 true
92 } else {
93 false
94 }
95 }
96
97 pub fn pop(&mut self) -> Option<T> {
99 self.queue.pop_front()
100 }
101
102 #[must_use]
104 pub fn is_empty(&self) -> bool {
105 self.queue.is_empty()
106 }
107}
108
109impl<T: std::hash::Hash + Eq + Clone> Default for WorkQueue<T> {
110 fn default() -> Self {
111 Self::new()
112 }
113}
114
115#[derive(Debug, Clone)]
117pub struct FrozenMap<K, V> {
118 map: FxHashMap<K, V>,
119}
120
121impl<K: std::hash::Hash + Eq, V> FrozenMap<K, V> {
122 #[must_use]
124 pub fn new(map: FxHashMap<K, V>) -> Self {
125 Self { map }
126 }
127
128 #[must_use]
130 pub fn get(&self, key: &K) -> Option<&V> {
131 self.map.get(key)
132 }
133
134 #[must_use]
136 pub fn contains_key(&self, key: &K) -> bool {
137 self.map.contains_key(key)
138 }
139
140 #[must_use]
142 pub fn len(&self) -> usize {
143 self.map.len()
144 }
145
146 #[must_use]
148 pub fn is_empty(&self) -> bool {
149 self.map.is_empty()
150 }
151
152 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
154 self.map.iter()
155 }
156}
157
158impl<K: std::hash::Hash + Eq, V> FromIterator<(K, V)> for FrozenMap<K, V> {
159 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
160 Self::new(iter.into_iter().collect())
161 }
162}
163
164#[derive(Debug, Clone)]
166pub struct UnionFind {
167 parent: Vec<usize>,
168 rank: Vec<usize>,
169}
170
171impl UnionFind {
172 #[must_use]
174 pub fn new(n: usize) -> Self {
175 Self {
176 parent: (0..n).collect(),
177 rank: vec![0; n],
178 }
179 }
180
181 pub fn find(&mut self, x: usize) -> usize {
183 if self.parent[x] != x {
184 self.parent[x] = self.find(self.parent[x]);
185 }
186 self.parent[x]
187 }
188
189 pub fn union(&mut self, x: usize, y: usize) {
191 let rx = self.find(x);
192 let ry = self.find(y);
193
194 if rx == ry {
195 return;
196 }
197
198 match self.rank[rx].cmp(&self.rank[ry]) {
199 std::cmp::Ordering::Less => self.parent[rx] = ry,
200 std::cmp::Ordering::Greater => self.parent[ry] = rx,
201 std::cmp::Ordering::Equal => {
202 self.parent[ry] = rx;
203 self.rank[rx] += 1;
204 }
205 }
206 }
207
208 pub fn same_set(&mut self, x: usize, y: usize) -> bool {
210 self.find(x) == self.find(y)
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 #[test]
219 fn test_work_queue() {
220 let mut wq: WorkQueue<i32> = WorkQueue::new();
221
222 assert!(wq.push(1));
223 assert!(wq.push(2));
224 assert!(!wq.push(1)); assert_eq!(wq.pop(), Some(1));
227 assert_eq!(wq.pop(), Some(2));
228 assert_eq!(wq.pop(), None);
229 }
230
231 #[test]
232 fn test_union_find() {
233 let mut uf = UnionFind::new(5);
234
235 uf.union(0, 1);
236 uf.union(2, 3);
237 uf.union(1, 3);
238
239 assert!(uf.same_set(0, 3));
240 assert!(!uf.same_set(0, 4));
241 }
242}