orx_priority_queue/dary/daryheap.rs
1use super::heap::Heap;
2use crate::{positions::none::HeapPositionsNone, PriorityQueue};
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}
78impl<N, K, const D: usize> DaryHeap<N, K, D>
79where
80 N: Clone,
81 K: PartialOrd + Clone,
82{
83 /// Creates a new empty d-ary heap.
84 ///
85 /// # Examples
86 ///
87 /// ```
88 /// use orx_priority_queue::*;
89 ///
90 /// let mut heap = BinaryHeap::new();
91 ///
92 /// heap.push('a', 4);
93 /// heap.push('b', 42);
94 ///
95 /// assert_eq!(Some('a'), heap.pop_node());
96 /// assert_eq!(Some('b'), heap.pop_node());
97 /// assert!(heap.is_empty());
98 /// ```
99 pub fn new() -> Self {
100 Self::default()
101 }
102
103 /// Creates a new d-ary heap with the given initial `capacity` on the number of nodes to simultaneously exist on the heap.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use orx_priority_queue::*;
109 ///
110 /// // create a queue with an expected space complexity of 4
111 /// let mut queue = DaryHeap::<_, _, 4>::with_capacity(4);
112 /// queue.push('a', 4);
113 /// assert_eq!(Some('a'), queue.pop_node());
114 /// ```
115 pub fn with_capacity(capacity: usize) -> Self {
116 Self {
117 heap: Heap::new(Some(capacity), HeapPositionsNone),
118 }
119 }
120
121 /// Returns the 'd' of the d-ary heap.
122 /// In other words, it represents the maximum number of children that each node on the heap can have.
123 pub const fn d() -> usize {
124 D
125 }
126
127 // additional functionalities
128 /// Returns the nodes and keys currently in the queue as a slice;
129 /// not necessarily sorted.
130 ///
131 /// # Examples
132 ///
133 /// ```
134 /// use orx_priority_queue::*;
135 ///
136 /// let mut queue = QuaternaryHeapWithMap::default();
137 /// queue.push("x", 42);
138 /// queue.push("y", 7);
139 /// queue.push("z", 99);
140 ///
141 /// let slice = queue.as_slice();
142 ///
143 /// assert_eq!(3, slice.len());
144 /// assert!(slice.contains(&("x", 42)));
145 /// assert!(slice.contains(&("y", 7)));
146 /// assert!(slice.contains(&("z", 99)));
147 /// ```
148 pub fn as_slice(&self) -> &[(N, K)] {
149 self.heap.as_slice()
150 }
151}
152
153impl<N, K, const D: usize> PriorityQueue<N, K> for DaryHeap<N, K, D>
154where
155 N: Clone,
156 K: PartialOrd + Clone,
157{
158 type NodeKey<'a>
159 = &'a (N, K)
160 where
161 Self: 'a,
162 N: 'a,
163 K: 'a;
164 type Iter<'a>
165 = core::slice::Iter<'a, (N, K)>
166 where
167 Self: 'a,
168 N: 'a,
169 K: 'a;
170
171 #[inline(always)]
172 fn len(&self) -> usize {
173 self.heap.len()
174 }
175
176 #[inline(always)]
177 fn capacity(&self) -> usize {
178 self.heap.capacity()
179 }
180
181 fn peek(&self) -> Option<&(N, K)> {
182 self.heap.peek()
183 }
184
185 fn clear(&mut self) {
186 self.heap.clear()
187 }
188
189 #[inline(always)]
190 fn pop(&mut self) -> Option<(N, K)> {
191 self.heap.pop()
192 }
193
194 #[inline(always)]
195 fn pop_node(&mut self) -> Option<N> {
196 self.heap.pop_node()
197 }
198
199 #[inline(always)]
200 fn pop_key(&mut self) -> Option<K> {
201 self.heap.pop_key()
202 }
203
204 #[inline(always)]
205 fn push(&mut self, node: N, key: K) {
206 self.heap.push(node, key)
207 }
208
209 #[inline(always)]
210 fn push_then_pop(&mut self, node: N, key: K) -> (N, K) {
211 self.heap.push_then_pop(node, key)
212 }
213
214 fn iter(&self) -> Self::Iter<'_> {
215 self.as_slice().iter()
216 }
217}