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}