orx_priority_queue/dary/daryheap.rs
1use super::heap::Heap;
2use crate::{PriorityQueue, positions::none::HeapPositionsNone};
3
4/// Type alias for `DaryHeap<N, K, 2>`; see [`DaryHeap`] for details.
5pub type BinaryHeap<N, K> = DaryHeap<N, K, 2>;
6/// Type alias for `DaryHeap<N, K, 4>`; see [`DaryHeap`] for details.
7pub type QuaternaryHeap<N, K> = DaryHeap<N, K, 4>;
8
9/// A d-ary heap which implements `PriorityQueue`, but not `PriorityQueueDecKey`.
10///
11/// *Its interface is similar to `std::collections:BinaryHeap; however, provides a generalization by allowing different d values.
12/// `DaryHeapMap` and DaryHeapOfIndices` on the other hand, provides the additional functionality of `PriorityQueueDecKey`
13/// which are crucial for providing better space complexity in algorithms such as the Dijkstra's shortest path algorithm.*
14///
15/// # Examples
16///
17/// ## Heap as a `PriorityQueue`
18///
19/// Usage of d-ary heap as a basic priority queue.
20///
21/// ```
22/// use orx_priority_queue::*;
23///
24/// fn test_priority_queue<P>(mut pq: P)
25/// where
26/// P: PriorityQueue<usize, f64>
27/// {
28/// pq.clear();
29///
30/// pq.push(0, 42.0);
31/// assert_eq!(Some(&0), pq.peek().map(|x| x.node()));
32/// assert_eq!(Some(&42.0), pq.peek().map(|x| x.key()));
33///
34/// pq.push(1, 7.0);
35/// assert_eq!(Some(&1), pq.peek().map(|x| x.node()));
36/// assert_eq!(Some(&7.0), pq.peek().map(|x| x.key()));
37///
38/// let popped = pq.pop();
39/// assert_eq!(Some((1, 7.0)), popped);
40///
41/// let popped = pq.pop();
42/// assert_eq!(Some((0, 42.0)), popped);
43///
44/// assert!(pq.is_empty());
45/// }
46///
47/// // basic d-heap without any means to located existing nodes
48/// test_priority_queue(DaryHeap::<_, _, 4>::default());
49/// test_priority_queue(DaryHeap::<_, _, 3>::with_capacity(16));
50/// // using type aliases to simplify signatures
51/// test_priority_queue(BinaryHeap::default());
52/// test_priority_queue(BinaryHeap::with_capacity(16));
53/// test_priority_queue(QuaternaryHeap::default());
54/// test_priority_queue(QuaternaryHeap::with_capacity(16));
55/// test_priority_queue(QuaternaryHeap::default());
56/// test_priority_queue(QuaternaryHeap::with_capacity(16));
57/// ```
58#[derive(Clone, Debug)]
59pub struct DaryHeap<N, K, const D: usize = 2>
60where
61 N: Clone,
62 K: PartialOrd + Clone,
63{
64 heap: Heap<N, K, HeapPositionsNone, D>,
65}
66
67impl<N, K, const D: usize> Default for DaryHeap<N, K, D>
68where
69 N: Clone,
70 K: PartialOrd + Clone,
71{
72 fn default() -> Self {
73 Self {
74 heap: Heap::new(None, HeapPositionsNone),
75 }
76 }
77}
78
79impl<N, K, const D: usize> FromIterator<(N, K)> for DaryHeap<N, K, D>
80where
81 N: Clone,
82 K: PartialOrd + Clone,
83{
84 fn from_iter<I: IntoIterator<Item = (N, K)>>(iter: I) -> Self {
85 Self {
86 heap: Heap::from_iter(iter, HeapPositionsNone),
87 }
88 }
89}
90
91impl<N, K, const D: usize> DaryHeap<N, K, D>
92where
93 N: Clone,
94 K: PartialOrd + Clone,
95{
96 /// Creates a new empty d-ary heap.
97 ///
98 /// # Examples
99 ///
100 /// ```
101 /// use orx_priority_queue::*;
102 ///
103 /// let mut heap = BinaryHeap::new();
104 ///
105 /// heap.push('a', 4);
106 /// heap.push('b', 42);
107 ///
108 /// assert_eq!(Some('a'), heap.pop_node());
109 /// assert_eq!(Some('b'), heap.pop_node());
110 /// assert!(heap.is_empty());
111 /// ```
112 pub fn new() -> Self {
113 Self::default()
114 }
115
116 /// Creates a new d-ary heap with the given initial `capacity` on the number of nodes to simultaneously exist on the heap.
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use orx_priority_queue::*;
122 ///
123 /// // create a queue with an expected space complexity of 4
124 /// let mut queue = DaryHeap::<_, _, 4>::with_capacity(4);
125 /// queue.push('a', 4);
126 /// assert_eq!(Some('a'), queue.pop_node());
127 /// ```
128 pub fn with_capacity(capacity: usize) -> Self {
129 Self {
130 heap: Heap::new(Some(capacity), HeapPositionsNone),
131 }
132 }
133
134 /// Returns the 'd' of the d-ary heap.
135 /// In other words, it represents the maximum number of children that each node on the heap can have.
136 pub const fn d() -> usize {
137 D
138 }
139
140 // additional functionalities
141 /// Returns the nodes and keys currently in the queue as a slice;
142 /// not necessarily sorted.
143 ///
144 /// # Examples
145 ///
146 /// ```
147 /// use orx_priority_queue::*;
148 ///
149 /// let mut queue = QuaternaryHeapWithMap::default();
150 /// queue.push("x", 42);
151 /// queue.push("y", 7);
152 /// queue.push("z", 99);
153 ///
154 /// let slice = queue.as_slice();
155 ///
156 /// assert_eq!(3, slice.len());
157 /// assert!(slice.contains(&("x", 42)));
158 /// assert!(slice.contains(&("y", 7)));
159 /// assert!(slice.contains(&("z", 99)));
160 /// ```
161 pub fn as_slice(&self) -> &[(N, K)] {
162 self.heap.as_slice()
163 }
164}
165
166impl<N, K, const D: usize> PriorityQueue<N, K> for DaryHeap<N, K, D>
167where
168 N: Clone,
169 K: PartialOrd + Clone,
170{
171 type NodeKey<'a>
172 = &'a (N, K)
173 where
174 Self: 'a,
175 N: 'a,
176 K: 'a;
177 type Iter<'a>
178 = core::slice::Iter<'a, (N, K)>
179 where
180 Self: 'a,
181 N: 'a,
182 K: 'a;
183
184 #[inline(always)]
185 fn len(&self) -> usize {
186 self.heap.len()
187 }
188
189 #[inline(always)]
190 fn capacity(&self) -> usize {
191 self.heap.capacity()
192 }
193
194 fn peek(&self) -> Option<&(N, K)> {
195 self.heap.peek()
196 }
197
198 fn clear(&mut self) {
199 self.heap.clear()
200 }
201
202 #[inline(always)]
203 fn pop(&mut self) -> Option<(N, K)> {
204 self.heap.pop()
205 }
206
207 #[inline(always)]
208 fn pop_node(&mut self) -> Option<N> {
209 self.heap.pop_node()
210 }
211
212 #[inline(always)]
213 fn pop_key(&mut self) -> Option<K> {
214 self.heap.pop_key()
215 }
216
217 #[inline(always)]
218 fn push(&mut self, node: N, key: K) {
219 self.heap.push(node, key)
220 }
221
222 #[inline(always)]
223 fn push_then_pop(&mut self, node: N, key: K) -> (N, K) {
224 self.heap.push_then_pop(node, key)
225 }
226
227 fn iter(&self) -> Self::Iter<'_> {
228 self.as_slice().iter()
229 }
230}