Queue Data Structure
Another simplest data structure after stack is the "Queue" data structure. As we know the stack data structure is based on LIFO (Last In, First Out), the queue data structure is based on exactly opposite FIFO (First In, First Out). So, first element inserted will be the first element to go out.
Let's start with out Queue struct.
pub struct Queue {
items: Vec<i32>
}
We got an items
field representing a vector that only accepts i32
items. We could implement it without any array or vector like stack's implementation but for the sake of simplicity we will use vector this time.
Let's see the implementation of this struct:
impl Queue {
pub fn new() -> Queue {
Queue { items: Vec::new() }
}
pub fn enqueue(&mut self, item: i32) {
self.items.push(item);
}
pub fn dequeue(&mut self) -> Option<i32> {
self.items.pop()
}
pub fn peek(&self) -> Option<&i32> {
self.items.last()
}
pub fn size(&self) -> usize {
self.items.len()
}
}
All the methods are pretty straight forward, enqueue
and dequeue
methods simply perform push and pop operations using the built in functionality from the vector.
While the additional methods like peek
and size
also using built in functionality from the vector.
Here is the full implementation with tests:
pub struct Queue {
items: Vec<i32>
}
impl Queue {
pub fn new() -> Queue {
Queue { items: Vec::new() }
}
pub fn enqueue(&mut self, item: i32) {
self.items.push(item);
}
pub fn dequeue(&mut self) -> Option<i32> {
self.items.pop()
}
pub fn peek(&self) -> Option<&i32> {
self.items.last()
}
pub fn size(&self) -> usize {
self.items.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let mut q = Queue::new();
assert_eq!(q.size(), 0);
assert_eq!(q.peek(), None);
assert_eq!(q.dequeue(), None);
}
#[test]
fn enqueue_works() {
let mut q = Queue::new();
q.enqueue(1);
assert_eq!(q.size(), 1);
assert_eq!(q.peek(), Some(&1));
}
#[test]
fn dequeue_works() {
let mut q = Queue::new();
q.enqueue(1);
assert_eq!(q.dequeue(), Some(1));
assert_eq!(q.size(), 0);
assert_eq!(q.peek(), None);
}
#[test]
fn peek_works() {
let mut q = Queue::new();
q.enqueue(1);
assert_eq!(q.peek(), Some(&1));
}
#[test]
fn size_works() {
let mut q = Queue::new();
q.enqueue(1);
assert_eq!(q.size(), 1);
}
}
Time Complexity
Both enqueue
and dequeue
methods have time complexity of O(1) because vectors in Rust have O(1) indexing and push and pop operations in vector also take O(1) complexity.