Stacks and Queues

While Rust's standard library doesn't have dedicated Stack and Queue types in the same way some other languages do, you can easily use existing data structures instead - primarily Vec↗ for stack-like behavior, and VecDeque↗ for queue-like behavior.

Implement a Stack Using Vec

std cat~data-structures

A stack is a LIFO (Last-In, First-Out) data structure. You can use a Vec to mimic a stack, because Vec provides efficient push (add to the top) and pop (remove from the top) operations.

fn main() {
    // Initialize a stack with a minimum capacity.
    // The stack will be able to hold at least 5 elements without reallocating:
    let mut stack = Vec::with_capacity(5);
    assert_eq!(stack.capacity(), 5);
    assert_eq!(stack.len(), 0);

    // Append elements to the back of the `Vec` / top of the stack:
    stack.push(1);
    stack.push(22);
    stack.push(333);

    // Peek at the top (last) element of the stack, or `None` if it is empty
    println!("Top element: {:?}", stack.last());
    assert_eq!(stack.last(), Some(&333));

    // Remove and return the top (last) element if the predicate returns true,
    // or `None` if the predicate returns false or the vector is empty.
    assert_eq!(stack.pop_if(|x: &mut i32| *x % 2 == 0), None);

    // `pop` removes and returns the top (last) element.
    // It returns `None` if the stack is empty.
    while let Some(top) = stack.pop() {
        // Pop elements until the stack is empty.
        println!("Popped: {top}");
    }

    println!("Stack is empty: {}", stack.is_empty());
}

Implement a Queue Using VecDeque

std cat~data-structures

A queue is a FIFO (First-In, First-Out) data structure. VecDeque (Vector Deque) is well-suited for implementing queues, because it provides efficient push_back (add to the rear) and pop_front (remove from the front) operations:

use std::collections::VecDeque;

fn main() {
    let mut queue = VecDeque::new();
    // You can also use `with_capacity`.

    // Add to the queue:
    queue.push_back(1);
    queue.push_back(2);
    queue.push_back(3);

    // Initialize a queue from an array:
    let mut q2 = VecDeque::from([4, 5]);

    // Append to the first queue:
    queue.append(&mut q2);

    // Peek at the front element:
    println!("Front element: {:?}", queue.front());

    // Dequeue elements from the front, until the queue is empty.
    while let Some(front) = queue.pop_front() {
        println!("Dequeued: {front}");
    }
    // Consider using `pop_front_if` as well.

    println!("Queue is empty: {}", queue.is_empty());

    // `VecDeque` is in fact a double-ended queue that offers `push_front`,
    // `back`, `back_mut`, `pop_back`, `pop_back_if` operations:
    queue.push_front(-1);
    queue.push_front(-2);
    assert_eq!(queue.back(), Some(&-1));
}
  • Binary Heaps.
  • Linked Lists.
  • Vectors.