flex_algo/priority_queue.rs
1//! PriorityQueue
2//!
3//! This data structure implements a Priority Queue with a comparator function to specify the Min/Max heap.
4//! The queue is implemented as a heap of indexes.
5///
6/// # Example
7///
8/// ```
9/// use flex_algo::priority_queue::PriorityQueue;
10///
11/// let mut pq = PriorityQueue::new(|a: &usize,b: &usize| a < b);
12/// pq.push(0);
13/// pq.push(1);
14/// pq.push(2);
15///
16/// let value = pq.pop().unwrap();
17/// assert_eq!(value, 0);
18/// ```
19///
20use std::fmt::Debug;
21
22/// PriorityQueue
23///
24/// This data structure implements a Priority Queue with a comparator function to specify the Min/Max heap.
25/// The queue is implemented as a heap of indexes.
26///
27#[derive(Debug)]
28pub struct PriorityQueue<F, T>
29where
30 F: Fn(&T, &T) -> bool,
31 T: PartialOrd + Debug,
32{
33 heap: Vec<T>,
34 comparator: F,
35}
36
37impl<F, T> PriorityQueue<F, T>
38where
39 F: Fn(&T, &T) -> bool,
40 T: PartialOrd + Debug,
41{
42 /// Create a new PriorityQueue with a comparator function
43 ///
44 /// # Example
45 ///
46 /// ```
47 /// use flex_algo::priority_queue::PriorityQueue;
48 ///
49 /// let mut pq = PriorityQueue::new(|a: &usize,b: &usize| a < b);
50 ///
51 /// ```
52 pub fn new(comparator: F) -> Self {
53 PriorityQueue {
54 heap: Vec::new(),
55 comparator,
56 }
57 }
58
59 /// Return the size of the PriorityQueue
60 ///
61 /// # Example
62 ///
63 /// ```
64 /// use flex_algo::priority_queue::PriorityQueue;
65 ///
66 /// let mut pq = PriorityQueue::new(|a: &usize,b: &usize| a < b);
67 /// assert_eq!(pq.size(), 0);
68 /// ```
69 pub fn size(&self) -> usize {
70 self.heap.len()
71 }
72
73 /// Return true if the PriorityQueue is empty
74 ///
75 /// # Example
76 ///
77 /// ```
78 /// use flex_algo::priority_queue::PriorityQueue;
79 ///
80 /// let mut pq = PriorityQueue::new(|a: &usize,b: &usize| a < b);
81 /// assert_eq!(pq.is_empty(), true);
82 /// ```
83 pub fn is_empty(&self) -> bool {
84 self.heap.len() == 0
85 }
86
87 fn _parent(&self, idx: usize) -> usize {
88 (idx - 1) / 2
89 }
90
91 fn _left_child(&self, idx: usize) -> usize {
92 2 * idx + 1
93 }
94
95 fn _right_child(&self, idx: usize) -> usize {
96 2 * idx + 2
97 }
98
99 fn _compare(&self, i: usize, j: usize) -> bool {
100 (self.comparator)(self.heap.get(i).unwrap(), self.heap.get(j).unwrap())
101 }
102
103 fn _swap(&mut self, i: usize, j: usize) {
104 self.heap.swap(i, j);
105 }
106
107 fn _sift_up(&mut self) {
108 let mut node_index = self.size() - 1;
109 while node_index > 0 && self._compare(node_index, self._parent(node_index)) {
110 self._swap(node_index, self._parent(node_index));
111 node_index = self._parent(node_index);
112 }
113 }
114
115 /// Push element into Priority Queue and return the size of the PriorityQueue
116 ///
117 /// # Example
118 ///
119 /// ```
120 /// use flex_algo::priority_queue::PriorityQueue;
121 ///
122 /// let mut pq = PriorityQueue::new(|a: &usize,b: &usize| a < b);
123 /// pq.push(14);
124 /// pq.push(10);
125 /// let len = pq.push(12);
126 ///
127 /// assert_eq!(len, 3);
128 /// ```
129 pub fn push(&mut self, value: T) -> usize {
130 self.heap.push(value);
131 self._sift_up();
132 self.heap.len()
133 }
134
135 fn _sift_down(&mut self) {
136 let mut node_index = 0;
137 while (self._left_child(node_index) < self.size()
138 && self._compare(self._left_child(node_index), node_index))
139 || (self._right_child(node_index) < self.size()
140 && self._compare(self._right_child(node_index), node_index))
141 {
142 let mut greater_index = self._left_child(node_index);
143 if self._right_child(node_index) < self.size()
144 && self._compare(self._right_child(node_index), self._left_child(node_index))
145 {
146 greater_index = self._right_child(node_index);
147 }
148 self._swap(node_index, greater_index);
149 node_index = greater_index;
150 }
151 }
152
153 /// Return the first element of the heap, or `None` if it is empty.
154 ///
155 /// # Example
156 ///
157 /// ```
158 /// use flex_algo::priority_queue::PriorityQueue;
159 ///
160 /// let mut pq = PriorityQueue::new(|a: &usize,b: &usize| a < b);
161 /// pq.push(14);
162 /// pq.push(10);
163 /// pq.push(12);
164 ///
165 /// assert_eq!(pq.pop().unwrap(), 10);
166 /// ```
167 pub fn pop(&mut self) -> Option<T> {
168 if self.size() > 1 {
169 self._swap(0, self.size() - 1);
170 }
171 let value = self.heap.pop();
172 self._sift_down();
173 value
174 }
175
176 /// Return the first element of the heap, or `None` if it is empty without change the heap.
177 ///
178 /// # Example
179 ///
180 /// ```
181 /// use flex_algo::priority_queue::PriorityQueue;
182 ///
183 /// let mut pq = PriorityQueue::new(|a: &usize,b: &usize| a < b);
184 /// pq.push(14);
185 /// pq.push(10);
186 /// pq.push(12);
187 ///
188 /// assert_eq!(pq.peek().unwrap(), &10);
189 /// ```
190 pub fn peek(&self) -> Option<&T> {
191 self.heap.first()
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 fn compare(a: &usize, b: &usize) -> bool {
200 a > b
201 }
202
203 #[test]
204 fn test_priority_queue_function() {
205 let mut pq = PriorityQueue::new(compare);
206 assert_eq!(pq.size(), 0);
207 assert_eq!(pq._parent(1), 0);
208 assert_eq!(pq._parent(2), 0);
209 assert_eq!(pq._parent(3), 1);
210 assert_eq!(pq._left_child(1), 3);
211 assert_eq!(pq._right_child(1), 4);
212
213 pq.push(14);
214 pq.push(12);
215 pq.push(5);
216 pq.push(7);
217 pq.push(8);
218 pq.push(3);
219
220 println!("priority queue: {:?}", pq.heap);
221 assert_eq!(pq.heap.get(0).unwrap(), &14);
222 assert_eq!(pq.peek().unwrap(), &14);
223 assert_eq!(pq.pop().unwrap(), 14);
224 // panic!();
225 }
226
227 #[test]
228 fn test_priority_queue_closure() {
229 let distances = [1, 6, 14, 2, 7];
230 let mut pq = PriorityQueue::new(|a: &usize, b: &usize| distances[*a] < distances[*b]);
231 assert_eq!(pq.is_empty(), true);
232 pq.push(0);
233 pq.push(1);
234 pq.push(2);
235 pq.push(3);
236 pq.push(4);
237 println!("priority queue(closure): {:?}", pq.heap);
238 let value = pq.pop().unwrap();
239 println!("priority queue(closure): {:?}", pq.heap);
240 assert_eq!(value, 0);
241 // panic!();
242 }
243}