orx_priority_queue/dary/daryheap_map.rs
1use super::heap::Heap;
2use crate::{
3 positions::map::{HeapPositionsMap, Index},
4 PriorityQueue, PriorityQueueDecKey, ResUpdateKey,
5};
6
7/// Type alias for `DaryHeapWithMap<N, K, 2>`; see [`DaryHeapWithMap`] for details.
8pub type BinaryHeapWithMap<N, K> = DaryHeapWithMap<N, K, 2>;
9/// Type alias for `DaryHeapWithMap<N, K, 4>`; see [`DaryHeapWithMap`] for details.
10pub type QuaternaryHeapWithMap<N, K> = DaryHeapWithMap<N, K, 4>;
11
12/// A d-ary heap which implements both `PriorityQueue` and `PriorityQueueDecKey`.
13///
14/// See [`PriorityQueueDecKey`] for additional functionalities.
15///
16/// `DaryHeapWithMap` achieves the additional features by making use of a map of nodes to positions on the heap.
17///
18/// # Flexibility (`DaryHeapWithMap`) vs Performance (`DaryHeapOfIndices`)
19///
20/// [`DaryHeapWithMap`] (hence its variants such as [`BinaryHeapWithMap`]) does not require to know
21/// the absolute size of the closed set.
22/// Furthermore, the node type needs to implement `Hash + Eq` rather than `HasIndex` trait defined in this crate.
23/// Due to these, `DaryHeapWithMap` might be considered as the more flexible [`PriorityQueueDecKey`] variant.
24///
25/// On the other hand, `DaryHeapOfIndices` (hence its variants such as `BinaryHeapOfIndices`),
26/// provides significantly faster accesses to positions of nodes on the heap.
27/// This is important for [`PriorityQueueDecKey`] operations such as `decrease_key` or `contains`.
28/// Furthermore, in many algorithms such as certain network algorithms where nodes enter and exit the queue,
29/// `index_bound` can often trivially be set to number of nodes.
30///
31/// # Examples
32///
33/// ## Heap as a `PriorityQueue`
34///
35/// Usage of d-ary heap as a basic priority queue.
36///
37/// ```
38/// use orx_priority_queue::*;
39///
40/// fn test_priority_queue<P>(mut pq: P)
41/// where
42/// P: PriorityQueue<usize, f64>
43/// {
44/// pq.clear();
45///
46/// pq.push(0, 42.0);
47/// assert_eq!(Some(&0), pq.peek().map(|x| x.node()));
48/// assert_eq!(Some(&42.0), pq.peek().map(|x| x.key()));
49///
50/// pq.push(1, 7.0);
51/// assert_eq!(Some(&1), pq.peek().map(|x| x.node()));
52/// assert_eq!(Some(&7.0), pq.peek().map(|x| x.key()));
53///
54/// let popped = pq.pop();
55/// assert_eq!(Some((1, 7.0)), popped);
56///
57/// let popped = pq.pop();
58/// assert_eq!(Some((0, 42.0)), popped);
59///
60/// assert!(pq.is_empty());
61/// }
62///
63/// // d-ary heap using a hash map to locate existing nodes (although decrease-key is not used here)
64/// test_priority_queue(DaryHeapWithMap::<_, _, 3>::default());
65/// test_priority_queue(DaryHeapWithMap::<_, _, 4>::with_capacity(16));
66/// // using type aliases to simplify signatures
67/// test_priority_queue(BinaryHeapWithMap::default());
68/// test_priority_queue(BinaryHeapWithMap::with_capacity(16));
69/// test_priority_queue(QuaternaryHeapWithMap::default());
70/// test_priority_queue(QuaternaryHeapWithMap::with_capacity(16));
71/// test_priority_queue(QuaternaryHeapWithMap::default());
72/// test_priority_queue(QuaternaryHeapWithMap::with_capacity(16));
73/// ```
74///
75/// ## Heap as a `PriorityQueueDecKey`
76///
77/// Usage of a d-ary heap as a priority queue with decrease key operation and its variants.
78///
79/// ```
80/// use orx_priority_queue::*;
81///
82/// fn test_priority_queue_deckey<P>(mut pq: P)
83/// where
84/// P: PriorityQueueDecKey<usize, f64>
85/// {
86/// pq.clear();
87///
88/// pq.push(0, 42.0);
89/// assert_eq!(Some(&0), pq.peek().map(|x| x.node()));
90/// assert_eq!(Some(&42.0), pq.peek().map(|x| x.key()));
91///
92/// pq.push(1, 17.0);
93/// assert_eq!(Some(&1), pq.peek().map(|x| x.node()));
94/// assert_eq!(Some(&17.0), pq.peek().map(|x| x.key()));
95///
96/// pq.decrease_key(&0, 7.0);
97/// assert_eq!(Some(&0), pq.peek().map(|x| x.node()));
98/// assert_eq!(Some(&7.0), pq.peek().map(|x| x.key()));
99///
100/// let res_try_deckey = pq.try_decrease_key(&1, 20.0);
101/// assert_eq!(res_try_deckey, ResTryDecreaseKey::Unchanged);
102///
103/// let popped = pq.pop();
104/// assert_eq!(Some((0, 7.0)), popped);
105///
106/// let popped = pq.pop();
107/// assert_eq!(Some((1, 17.0)), popped);
108///
109/// assert!(pq.is_empty());
110/// }
111/// // d-ary heap using a hash map to locate existing nodes
112/// test_priority_queue_deckey(DaryHeapWithMap::<_, _, 3>::default());
113/// test_priority_queue_deckey(DaryHeapWithMap::<_, _, 4>::with_capacity(16));
114/// // using type aliases to simplify signatures
115/// test_priority_queue_deckey(BinaryHeapWithMap::default());
116/// test_priority_queue_deckey(BinaryHeapWithMap::with_capacity(16));
117/// test_priority_queue_deckey(QuaternaryHeapWithMap::default());
118/// test_priority_queue_deckey(QuaternaryHeapWithMap::with_capacity(16));
119/// test_priority_queue_deckey(QuaternaryHeapWithMap::default());
120/// test_priority_queue_deckey(QuaternaryHeapWithMap::with_capacity(16));
121/// ```
122#[derive(Debug, Clone)]
123pub struct DaryHeapWithMap<N, K, const D: usize = 2>
124where
125 N: Index,
126 K: PartialOrd + Clone,
127{
128 heap: Heap<N, K, HeapPositionsMap<N>, D>,
129}
130
131impl<N, K, const D: usize> Default for DaryHeapWithMap<N, K, D>
132where
133 N: Index,
134 K: PartialOrd + Clone,
135{
136 fn default() -> Self {
137 Self {
138 heap: Heap::new(None, HeapPositionsMap::default()),
139 }
140 }
141}
142impl<N, K, const D: usize> DaryHeapWithMap<N, K, D>
143where
144 N: Index,
145 K: PartialOrd + Clone,
146{
147 /// Creates a new empty d-ary heap.
148 ///
149 /// # Examples
150 ///
151 /// ```
152 /// use orx_priority_queue::*;
153 ///
154 /// let mut heap = BinaryHeapWithMap::new();
155 ///
156 /// heap.push('a', 4);
157 /// heap.push('b', 42);
158 ///
159 /// assert_eq!(Some('a'), heap.pop_node());
160 /// assert_eq!(Some('b'), heap.pop_node());
161 /// assert!(heap.is_empty());
162 /// ```
163 pub fn new() -> Self {
164 Self::default()
165 }
166
167 /// Creates a new d-ary heap with the given initial `capacity` on the number of nodes to simultaneously exist on the heap.
168 pub fn with_capacity(capacity: usize) -> Self {
169 Self {
170 heap: Heap::new(Some(capacity), HeapPositionsMap::with_capacity(capacity)),
171 }
172 }
173 /// Returns the 'd' of the d-ary heap.
174 /// In other words, it represents the maximum number of children that each node on the heap can have.
175 pub const fn d() -> usize {
176 D
177 }
178
179 // additional functionalities
180 /// Returns the nodes and keys currently in the queue as a slice;
181 /// not necessarily sorted.
182 ///
183 /// # Examples
184 ///
185 /// ```
186 /// use orx_priority_queue::*;
187 ///
188 /// let mut queue = QuaternaryHeapWithMap::default();
189 /// queue.push("x", 42);
190 /// queue.push("y", 7);
191 /// queue.push("z", 99);
192 ///
193 /// let slice = queue.as_slice();
194 ///
195 /// assert_eq!(3, slice.len());
196 /// assert!(slice.contains(&("x", 42)));
197 /// assert!(slice.contains(&("y", 7)));
198 /// assert!(slice.contains(&("z", 99)));
199 /// ```
200 pub fn as_slice(&self) -> &[(N, K)] {
201 self.heap.as_slice()
202 }
203}
204
205impl<N, K, const D: usize> PriorityQueue<N, K> for DaryHeapWithMap<N, K, D>
206where
207 N: Index,
208 K: PartialOrd + Clone,
209{
210 type NodeKey<'a> = &'a (N, K) where Self: 'a, N: 'a, K: 'a;
211 type Iter<'a> = core::slice::Iter<'a, (N, K)> where Self: 'a, N: 'a, K: 'a;
212
213 #[inline(always)]
214 fn len(&self) -> usize {
215 self.heap.len()
216 }
217
218 #[inline(always)]
219 fn capacity(&self) -> usize {
220 self.heap.capacity()
221 }
222
223 fn peek(&self) -> Option<&(N, K)> {
224 self.heap.peek()
225 }
226
227 fn clear(&mut self) {
228 self.heap.clear()
229 }
230
231 #[inline(always)]
232 fn pop(&mut self) -> Option<(N, K)> {
233 self.heap.pop()
234 }
235
236 #[inline(always)]
237 fn pop_node(&mut self) -> Option<N> {
238 self.heap.pop_node()
239 }
240
241 #[inline(always)]
242 fn pop_key(&mut self) -> Option<K> {
243 self.heap.pop_key()
244 }
245
246 #[inline(always)]
247 fn push(&mut self, node: N, key: K) {
248 self.heap.push(node, key)
249 }
250
251 #[inline(always)]
252 fn push_then_pop(&mut self, node: N, key: K) -> (N, K) {
253 self.heap.push_then_pop(node, key)
254 }
255
256 fn iter(&self) -> Self::Iter<'_> {
257 self.as_slice().iter()
258 }
259}
260impl<N, K, const D: usize> PriorityQueueDecKey<N, K> for DaryHeapWithMap<N, K, D>
261where
262 N: Index,
263 K: PartialOrd + Clone,
264{
265 #[inline(always)]
266 fn contains(&self, node: &N) -> bool {
267 self.heap.contains(node)
268 }
269
270 #[inline(always)]
271 fn key_of(&self, node: &N) -> Option<K> {
272 self.heap.key_of(node)
273 }
274
275 #[inline(always)]
276 fn decrease_key(&mut self, node: &N, decreased_key: K) {
277 self.heap.decrease_key(node, decreased_key)
278 }
279
280 #[inline(always)]
281 fn update_key(&mut self, node: &N, new_key: K) -> ResUpdateKey {
282 self.heap.update_key(node, new_key)
283 }
284
285 #[inline(always)]
286 fn remove(&mut self, node: &N) -> K {
287 self.heap.remove(node)
288 }
289}