Skip to main content

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}