Vec<T> in Depth
push() and pop()
The .push() and .pop() methods append an element to the back of a Vec<T> and remove the last element from the back, allowing Vec<T> to act as an efficient LIFO (Last-In, First-Out) stack.
Signatures and Complexity
impl<T> Vec<T> {
pub fn push(&mut self, value: T);
pub fn pop(&mut self) -> Option<T>;
pub fn pop_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T>;
}
Before: [ 10, 20, 30 | -- ] (len = 3, cap = 4)
▲
v.push(40): writes 40 at [3], increments len to 4:
[ 10, 20, 30, 40 ] (len = 4, cap = 4)
│
v.pop(): decrements len to 3 and moves 40 out as Some(40):
[ 10, 20, 30 | -- ] (len = 3, cap = 4)
| Method | Time Complexity | Effect on len and capacity |
|---|---|---|
v.push(val) |
Amortized $O(1)$ ($O(n)$ only when len == capacity) |
Increments len by 1; grows capacity if full |
v.pop() |
Guaranteed $O(1)$ | Decrements len by 1 if non-empty; never shrinks capacity |
v.pop_if(pred) |
Guaranteed $O(1)$ | Pops and returns the last element only if pred(&mut last) returns true |
Using Vec<T> as a LIFO Stack
fn is_balanced_brackets(expr: &str) -> bool {
let mut stack = Vec::new();
for ch in expr.chars() {
match ch {
'(' | '[' | '{' => stack.push(ch),
')' => {
if stack.pop() != Some('(') {
return false;
}
}
']' => {
if stack.pop() != Some('[') {
return false;
}
}
'}' => {
if stack.pop() != Some('{') {
return false;
}
}
_ => {}
}
}
stack.is_empty()
}
fn main() {
for sample in ["{[()]}", "{[(])}", "(()"] {
println!("{sample:<8} -> balanced: {}", is_balanced_brackets(sample));
}
}
{[()]} -> balanced: true
{[(])} -> balanced: false
(() -> balanced: false
Conditional Popping with pop_if() (Rust 1.86+)
Instead of checking v.last() and then calling v.pop().unwrap(), v.pop_if(|last| ...) inspects (and optionally mutates) the final element and pops it only when the predicate returns true:
fn main() {
let mut tasks = vec![10, 25, 99];
let urgent = tasks.pop_if(|&mut prio| prio >= 50);
let next_urgent = tasks.pop_if(|&mut prio| prio >= 50);
println!("First pop_if: {urgent:?}");
println!("Second pop_if: {next_urgent:?}");
println!("Remaining: {tasks:?}");
}
First pop_if: Some(99)
Second pop_if: None
Remaining: [10, 25]