pfds/queue.rs
1//
2// Copyright 2021-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30use std::sync::Arc;
31use std::marker::PhantomData;
32
33use crate::list::*;
34
35enum QueueNode<E: Clone> {
36 Empty,
37 Node { back: L<E>, front: L<E> },
38}
39
40use QueueNode::*;
41
42type N<E> = Arc<QueueNode<E>>;
43type L<E> = List<E>;
44
45fn empty<E: Clone>() -> N<E> {
46 Arc::new(Empty)
47}
48fn node<E: Clone>(back: L<E>, front: L<E>) -> N<E> {
49 match (back.len(), front.len()) {
50 (0, 0) => empty(),
51 _ => Arc::new(Node { back, front }),
52 }
53}
54
55fn enqueue<E: Clone>(q: &N<E>, e: E) -> N<E> {
56 match q.as_ref() {
57 Empty => node(L::empty().push(e), L::empty()),
58 Node { back: b, front: f } => node(b.push(e), f.clone()),
59 }
60}
61
62fn dequeue<E: Clone>(q: &N<E>) -> (E, N<E>) {
63 match q.as_ref() {
64 Empty => panic!("queue is empty"),
65 Node { back: b, front: f } => match (b.len(), f.len()) {
66 (0, 0) => unreachable!("node() invariant violated: Node should never have both lists empty"),
67 (_, 0) => {
68 let l = b.rev();
69 let p = l.pop();
70 (l.top().clone(), node(L::empty(), p))
71 }
72 (_, _) => {
73 let p = f.pop();
74 (f.top().clone(), node(b.clone(), p))
75 }
76 },
77 }
78}
79
80fn len<E: Clone>(q: &N<E>) -> usize {
81 match q.as_ref() {
82 Empty => 0,
83 Node { back: b, front: f } => b.len() + f.len(),
84 }
85}
86
87fn to_vec<E: Clone>(l: &N<E>) -> Vec<E> {
88 let mut v = Vec::new();
89 let mut n = l.clone();
90 loop {
91 match n.as_ref() {
92 Empty => return v,
93 _ => {
94 let (e, nn) = dequeue(&n);
95 v.push(e.clone());
96 n = nn;
97 }
98 }
99 }
100}
101
102/// A persistent (immutable) FIFO queue data structure.
103///
104/// `Queue` is implemented using two lists (front and back) to achieve
105/// amortized O(1) enqueue and dequeue operations. All operations return
106/// a new queue, leaving the original unchanged.
107///
108/// # Performance
109///
110/// - `enqueue`: O(1)
111/// - `dequeue`: O(1) amortized, O(n) worst case when reversing back list
112/// - `is_empty`: O(1)
113/// - `len`: O(1) - length is cached
114/// - `to_vec`: O(n)
115#[derive(Clone)]
116pub struct Queue<E: Clone> {
117 n: N<E>,
118}
119
120impl<E: Clone> Queue<E> {
121 /// Creates a new empty queue.
122 ///
123 /// # Examples
124 ///
125 /// ```
126 /// use pfds::Queue;
127 ///
128 /// let queue: Queue<i32> = Queue::empty();
129 /// assert!(queue.is_empty());
130 /// assert_eq!(queue.len(), 0);
131 /// ```
132 pub fn empty() -> Self {
133 Self { n: empty() }
134 }
135
136 /// Creates a new queue with the given element added to the back.
137 ///
138 /// This operation is O(1) and shares structure with the original queue.
139 ///
140 /// # Arguments
141 ///
142 /// * `e` - The element to add to the back of the queue
143 ///
144 /// # Examples
145 ///
146 /// ```
147 /// use pfds::Queue;
148 ///
149 /// let queue = Queue::empty().enqueue(1).enqueue(2).enqueue(3);
150 /// assert_eq!(queue.len(), 3);
151 /// ```
152 pub fn enqueue(&self, e: E) -> Self {
153 Self {
154 n: enqueue(&self.n, e),
155 }
156 }
157
158 /// Removes and returns the front element and a new queue without that element.
159 ///
160 /// This operation is O(1) amortized. When the front list is empty,
161 /// it reverses the back list which takes O(n) time.
162 ///
163 /// # Returns
164 ///
165 /// A tuple containing:
166 /// - The front element
167 /// - A new queue without the front element
168 ///
169 /// # Panics
170 ///
171 /// Panics if the queue is empty.
172 ///
173 /// # Examples
174 ///
175 /// ```
176 /// use pfds::Queue;
177 ///
178 /// let queue = Queue::empty().enqueue(1).enqueue(2);
179 /// let (first, queue2) = queue.dequeue();
180 /// assert_eq!(first, 1);
181 /// assert_eq!(queue.len(), 2); // Original unchanged
182 /// assert_eq!(queue2.len(), 1);
183 /// ```
184 pub fn dequeue(&self) -> (E, Self) {
185 let (e, n) = dequeue(&self.n);
186 (e, Self { n })
187 }
188
189 /// Returns true if the queue is empty.
190 ///
191 /// This operation is O(1).
192 ///
193 /// # Examples
194 ///
195 /// ```
196 /// use pfds::Queue;
197 ///
198 /// let empty = Queue::<i32>::empty();
199 /// assert!(empty.is_empty());
200 ///
201 /// let non_empty = empty.enqueue(1);
202 /// assert!(!non_empty.is_empty());
203 /// ```
204 pub fn is_empty(&self) -> bool {
205 len(&self.n) == 0
206 }
207
208 /// Returns the number of elements in the queue.
209 ///
210 /// This operation is O(1) as the length is cached.
211 ///
212 /// # Examples
213 ///
214 /// ```
215 /// use pfds::Queue;
216 ///
217 /// let queue = Queue::empty().enqueue(1).enqueue(2).enqueue(3);
218 /// assert_eq!(queue.len(), 3);
219 /// ```
220 pub fn len(&self) -> usize {
221 len(&self.n)
222 }
223
224 /// Converts the queue to a vector.
225 ///
226 /// Elements are returned in FIFO order (oldest elements first).
227 /// This operation is O(n).
228 ///
229 /// # Examples
230 ///
231 /// ```
232 /// use pfds::Queue;
233 ///
234 /// let queue = Queue::empty().enqueue(1).enqueue(2).enqueue(3);
235 /// let vec = queue.to_vec();
236 /// assert_eq!(vec, vec![1, 2, 3]); // FIFO order
237 /// ```
238 pub fn to_vec(&self) -> Vec<E> {
239 to_vec(&self.n)
240 }
241
242 /// Returns an iterator over the queue elements.
243 ///
244 /// The iterator yields elements in FIFO order (oldest first).
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use pfds::Queue;
250 ///
251 /// let queue = Queue::empty().enqueue(1).enqueue(2).enqueue(3);
252 /// let collected: Vec<_> = queue.iter().collect();
253 /// assert_eq!(collected, vec![1, 2, 3]);
254 /// ```
255 pub fn iter(&self) -> QueueIter<E> {
256 QueueIter {
257 queue: self.n.clone(),
258 _phantom: PhantomData::default(),
259 }
260 }
261}
262
263/// An iterator over the elements of a `Queue`.
264///
265/// This struct is created by the [`Queue::iter`] method.
266/// The iterator yields elements in FIFO order.
267pub struct QueueIter<'a, E: Clone> {
268 queue: N<E>,
269 _phantom: PhantomData<&'a E>,
270}
271
272impl<'a, E: Clone> std::iter::Iterator for QueueIter<'a, E> {
273 type Item = E;
274
275 fn next(&mut self) -> Option<Self::Item> {
276 match self.queue.as_ref() {
277 Empty => None,
278 _ => {
279 let (elem, new_queue) = dequeue(&self.queue);
280 self.queue = new_queue;
281 Some(elem)
282 }
283 }
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use crate::queue::*;
290
291 static mut SEED: i64 = 777;
292
293 fn rand() -> i32 {
294 unsafe {
295 SEED = SEED.wrapping_mul(1664525).wrapping_add(1013904223);
296 (SEED >> 24) as i32
297 }
298 }
299
300 #[test]
301 fn enqueue() {
302 let mut elements = Vec::new();
303 let mut l = Queue::empty();
304 for _ in 0..1000 {
305 let e = rand();
306 elements.push(e);
307 l = l.enqueue(e);
308 }
309
310 assert_eq!(elements.len(), 1000);
311 assert_eq!(elements.len(), l.len());
312
313 let queue_elems = l.to_vec();
314 for i in 0..1000 {
315 assert_eq!(queue_elems[i], elements[i]);
316 }
317 }
318
319 #[test]
320 fn dequeue() {
321 let mut elements = Vec::new();
322 let mut l = Queue::empty();
323 for _ in 0..100000 {
324 let e = rand();
325 elements.push(e);
326 l = l.enqueue(e);
327 }
328
329 assert_eq!(elements.len(), 100000);
330 assert_eq!(elements.len(), l.len());
331
332 let list_elems = l.to_vec();
333 for i in 0..100000 {
334 assert_eq!(list_elems[i], elements[i]);
335 }
336
337 for i in 0..50000 {
338 let (e, n) = l.dequeue();
339 let e2 = elements[i];
340 assert_eq!(e, e2);
341 l = n;
342 }
343
344 assert_eq!(l.len(), 50000);
345
346 let queue_elems = l.to_vec();
347 for i in 0..50000 {
348 assert_eq!(queue_elems[i], elements[i + 50000]);
349 }
350 }
351
352 #[test]
353 fn iter() {
354 let mut elements = Vec::new();
355 let mut q = Queue::empty();
356 for _ in 0..1000 {
357 let e = rand();
358 elements.push(e);
359 q = q.enqueue(e);
360 }
361
362 assert_eq!(elements.len(), 1000);
363 assert_eq!(elements.len(), q.len());
364
365 // Test iterator yields elements in FIFO order
366 let mut count = 0;
367 for elem in q.iter() {
368 assert_eq!(elem, elements[count]);
369 count += 1;
370 }
371 assert_eq!(count, 1000);
372
373 // Test that we can iterate multiple times (persistent data structure)
374 let collected: Vec<i32> = q.iter().collect();
375 assert_eq!(collected, elements);
376 }
377}