Standard Collections
Vec vs. VecDeque
Both Vec<T> and VecDeque<T> store elements in a growable heap-allocated array and support $O(1)$ random indexing, but they optimize for different insertion/removal ends and slice guarantees.
Architectural Comparison
Vec<T> (Contiguous from index 0; grows only to the right):
+----+----+----+----+----+----+
| e0 | e1 | e2 | e3 | -- | -- | push/pop at back = O(1)
+----+----+----+----+----+----+ insert/remove(0) = O(n) shift!
VecDeque<T> (Circular ring buffer; grows in both directions):
+----+----+----+----+----+----+
| e2 | e3 | -- | -- | e0 | e1 | push/pop at front OR back = O(1)
+----+----+----+----+----+----+ not a single &[T] slice when wrapped!
| Dimension | Vec<T> |
VecDeque<T> |
|---|---|---|
| Stack size (64-bit) | 24 bytes (ptr, len, capacity) |
32 bytes (ptr, capacity, head, len) |
| Push / pop at back | Amortized $O(1)$ (push, pop) |
Amortized $O(1)$ (push_back, pop_back) |
Push / pop at front (index 0) |
$O(n)$ (insert(0, x), remove(0)) |
Amortized $O(1)$ (push_front, pop_front) |
Random indexing (c[i]) |
$O(1)$ (ptr + i) |
$O(1)$ (ptr + (head + i) % cap, slightly more arithmetic) |
Coerces to &[T] slice? |
Yes (Deref<Target = [T]>) |
No — split across two slices (as_slices()) unless make_contiguous() is called |
Why Vec::remove(0) Is a Performance Bug on Queues
Using vec.remove(0) to dequeue from the front of a Vec<T> shifts all remaining $n - 1$ elements left by one slot on every dequeue. Draining $n$ items from the front of a Vec<T> takes $O(n^2)$ time, whereas draining $n$ items from the front of a VecDeque<T> with .pop_front() takes $O(n)$ time:
use std::collections::VecDeque;
fn main() {
// 1. LIFO Stack -> use `Vec<T>`:
let mut lifo_stack = Vec::new();
lifo_stack.push(1);
lifo_stack.push(2);
println!("LIFO pop (Vec): {:?}", lifo_stack.pop());
// 2. FIFO Queue -> use `VecDeque<T>`:
let mut fifo_queue = VecDeque::new();
fifo_queue.push_back(1);
fifo_queue.push_back(2);
println!("FIFO pop (VecDeque): {:?}", fifo_queue.pop_front());
}
LIFO pop (Vec): Some(2)
FIFO pop (VecDeque): Some(1)
Converting Between Vec<T> and VecDeque<T>
From<Vec<T>> is implemented for VecDeque<T> and From<VecDeque<T>> is implemented for Vec<T>. Converting a Vec<T> into a VecDeque<T> via VecDeque::from(vec) is an $O(1)$ zero-copy operation that reuses the existing heap allocation directly.