diff --git a/src/ch06_datastructures/mod.rs b/src/ch06_datastructures/mod.rs index 0c454f0..d397f7f 100644 --- a/src/ch06_datastructures/mod.rs +++ b/src/ch06_datastructures/mod.rs @@ -1,2 +1,3 @@ pub mod linked; pub mod linked_im; +pub mod queue; diff --git a/src/ch06_datastructures/queue.rs b/src/ch06_datastructures/queue.rs new file mode 100644 index 0000000..4d9b8a1 --- /dev/null +++ b/src/ch06_datastructures/queue.rs @@ -0,0 +1,109 @@ +use std::ptr; + +type Link = Option>>; + +pub struct Queue { + length: usize, + front: Link, + rear: *mut Node, +} + +struct Node { + value: T, + prev: Link, +} + +impl Queue { + pub fn new() -> Self { + Queue { + length: 0, + front: Option::None, + rear: ptr::null_mut(), + } + } + + pub fn len(&self) -> usize { + self.length + } + + pub fn enqueue(&mut self, value: T) { + let mut item = Box::new(Node { + value, + prev: Option::None, + }); + + let raw_rear: *mut _ = &mut *item; + + if self.rear.is_null() { + self.front = Some(item); + } else { + unsafe { + (*self.rear).prev = Some(item); + } + } + + self.rear = raw_rear; + + self.length = self.length + 1; + } + + pub fn dequeue(&mut self) -> Option { + self.front.take().map(|node| { + let front = *node; + self.front = front.prev; + + if self.front.is_none() { + self.rear = ptr::null_mut(); + } + + front.value + }) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_new_queue() { + let queue: Queue = Queue::new(); + assert_eq!(queue.len(), 0); + } + + #[test] + fn test_enqueue_len() { + let mut queue = Queue::new(); + queue.enqueue(32); + assert_eq!(queue.len(), 1); + queue.enqueue(50); + assert_eq!(queue.len(), 2); + } + + #[test] + fn test_deqeue() { + let mut queue: Queue = Queue::new(); + let result = queue.dequeue(); + assert_eq!(result, Option::None); + } + + #[test] + fn test_enqueue_dequeue() { + let mut queue = Queue::new(); + queue.enqueue(32); + queue.enqueue(50); + assert_eq!(queue.dequeue().unwrap(), 32); + assert_eq!(queue.dequeue().unwrap(), 50); + assert_eq!(queue.dequeue(), None); + } + + #[test] + fn test_enq_after_deq() { + // Specificially calls out hanging rear case + let mut queue = Queue::new(); + queue.enqueue(32); + queue.dequeue(); + queue.enqueue(100); + assert_eq!(queue.dequeue().unwrap(), 100); + } +}