A linked list stack allocates memory for each new element dynamically, so it grows as needed. An array stack allocates a fixed block of memory upfront, which may be larger than needed or may limit growth.
struct ArrayStack {
data: [i32; 5],
top: usize,
}
impl ArrayStack {
fn new() -> Self {
ArrayStack { data: [0; 5], top: 0 }
}
fn push(&mut self, val: i32) {
if self.top < 5 {
self.data[self.top] = val;
self.top += 1;
}
}
fn print_stack(&self) {
for i in (0..self.top).rev() {
print!("{} -> ", self.data[i]);
}
println!("null");
}
}
fn main() {
let mut stack = ArrayStack::new();
stack.push(10);
stack.push(20);
stack.push(30);
stack.print_stack();
}The last pushed element (30) is on top, so it prints first, followed by 20 and then 10.
struct Node {
val: i32,
next: Option<Box<Node>>,
}
struct LinkedListStack {
head: Option<Box<Node>>,
}
impl LinkedListStack {
fn new() -> Self {
LinkedListStack { head: None }
}
fn push(&mut self, val: i32) {
let new_node = Box::new(Node { val, next: self.head.take() });
self.head = Some(new_node);
}
fn pop(&mut self) -> Option<i32> {
if let Some(node) = self.head.take() {
self.head = node.next;
Some(node.val)
} else {
None
}
}
fn print_stack(&self) {
let mut current = &self.head;
while let Some(node) = current {
print!("{} -> ", node.val);
current = &node.next;
}
println!("null");
}
}
fn main() {
let mut stack = LinkedListStack::new();
stack.push(5);
stack.push(15);
stack.push(25);
stack.pop();
stack.pop();
stack.print_stack();
}After pushing 5, 15, 25, the stack top is 25. Two pops remove 25 and 15, leaving 5 on top.
Linked list push is always O(1) as it adds a node at the head. Array stack push is usually O(1), but resizing the array when full causes O(n) time occasionally.
A linked list stack grows dynamically as needed, making it suitable when maximum size is unknown. Fixed-size arrays risk overflow or wasted memory.
