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}