Collection Adapters and Specialized Types
push_front() and push_back()
The .push_front(value) and .push_back(value) methods on VecDeque<T> (and LinkedList<T>) insert an element at the beginning (logical index 0) or end (logical index len) of the sequence in amortized $O(1)$ time.
Signatures and Ring-Buffer Mechanics
impl<T> VecDeque<T> {
pub fn push_front(&mut self, value: T);
pub fn push_back(&mut self, value: T);
}
Initial Ring Buffer (capacity = 4, head = 0, len = 2):
+------+------+------+------+
| 10 | 20 | -- | -- | Logical view: [10, 20]
+------+------+------+------+
[0] [1] [2] [3]
▲
head
1. q.push_back(30) ──> writes at (head + len) % 4 = [2], len becomes 3:
+------+------+------+------+
| 10 | 20 | 30 | -- | Logical view: [10, 20, 30]
+------+------+------+------+
2. q.push_front(5) ──> decrements head modulo 4 to [3], writes 5 at [3], len becomes 4:
+------+------+------+------+
| 10 | 20 | 30 | 5 | Logical view: [5, 10, 20, 30]
+------+------+------+------+
▲
head
Notice that q.push_front(5) wraps head around to the end of the physical buffer ([3]) without moving 10, 20, or 30!
Building a Deque from Both Ends
push_front and push_back allow you to prioritize urgent items at the front of a work queue while appending normal items to the back:
use std::collections::VecDeque;
fn main() {
let mut jobs = VecDeque::new();
// Normal jobs go to the back (FIFO):
jobs.push_back("sync_logs");
jobs.push_back("generate_report");
// High-priority interrupt goes to the front (LIFO / urgent):
jobs.push_front("handle_healthcheck");
println!("Execution order: {jobs:?}");
}
Execution order: ["handle_healthcheck", "sync_logs", "generate_report"]
Sliding Window / Bounded History Buffer Pattern
Combining push_back with pop_front when len == max_len maintains a fixed-capacity rolling history of the most recent $N$ events in $O(1)$ time per event with zero reallocations after warm-up:
use std::collections::VecDeque;
struct RecentHistory<T> {
buf: VecDeque<T>,
max_items: usize,
}
impl<T> RecentHistory<T> {
fn new(max_items: usize) -> Self {
Self {
buf: VecDeque::with_capacity(max_items),
max_items,
}
}
fn record(&mut self, item: T) {
if self.buf.len() == self.max_items {
self.buf.pop_front(); // Evict oldest item in O(1)
}
self.buf.push_back(item); // Append newest item in O(1)
}
}
fn main() {
let mut history = RecentHistory::new(3);
for cmd in ["ls", "cd src", "cargo check", "cargo test"] {
history.record(cmd);
}
println!("Last 3 commands: {:?}", history.buf);
}
Last 3 commands: ["cd src", "cargo check", "cargo test"]