DSA Notes
Complete linked list stack implementation with all operations, memory analysis, comparison with array-based stack, understanding the true O(1) guarantee vs amortized O(1), and the practical scenarios where linked list stacks are preferred over array stacks.
Why a Linked List Stack?
Array-based stacks have O(1) amortized push — occasionally a resize triggers O(n) work. Linked list stacks have O(1) guaranteed push — every single push is exactly one node allocation and two pointer assignments.
This distinction matters in:
- Real-time systems: Where individual operation latency must be bounded
- Embedded systems: Where memory must be allocated and freed precisely
- Functional languages: Where persistent (immutable) stacks are natural with linked lists
Memory Model
Each push allocates a new node object in the heap. For n elements:
| Address 1000: StackNode { data=4, next= | 1048 } ← head (top) |
| Address 1048: StackNode { data=3, next= | 2200 } |
| Address 2200: StackNode { data=2, next= | 3100 } |
| Address 3100 | StackNode { data=1, next=None } ← bottom |
Memory per element:
- Python object overhead: ~28 bytes per StackNode (with
__slots__) - Without
__slots__: ~56+ bytes per StackNode - Compare: Python list element ≈ 8 bytes (pointer to object)
Step-by-Step Operation Trace
True O(1) vs Amortized O(1)
The distinction is important in time-critical systems:
| Operations | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
| cost | ↑ ↑ |
| resize(8 | 16) resize(16→32) |
| Operations | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
In soft real-time systems (audio processing, game physics), the occasional spike from array resizing may cause glitches. Linked list stacks eliminate this.
Persistent (Immutable) Stack
One powerful use of linked list stacks: sharing tails between versions.
Comparison — Array vs Linked List Stack
| Aspect | Array Stack | Linked List Stack |
|---|---|---|
| Push | O(1) amortized | O(1) guaranteed |
| Pop | O(1) | O(1) |
| Peek | O(1) | O(1) |
| Memory per element | ~8 bytes (pointer) | ~28 bytes (node + pointer) |
| Cache performance | Excellent | Poor |
| Maximum size | RAM limit | RAM limit |
| Predictable latency | No (resize spikes) | Yes |
| Persistent/immutable | Requires copying | Natural (tail sharing) |
| Simple code | Yes | Slightly more |
| Memory overhead | Over-allocated | None |
Choose linked list stack when:
- You need guaranteed O(1) per operation (real-time constraints)
- Building a persistent/functional data structure
- Memory must be allocated/freed precisely
Choose array stack when:
- General-purpose use (99% of cases)
- Cache performance matters
- Simpler code is preferred
Summary
The linked list stack is:
- True O(1) for push and pop — no amortization
- Natural for persistence — tail sharing enables immutable stacks without copying
- Higher memory overhead — node objects cost more than raw array slots
- Poor cache performance — scattered heap allocations vs. contiguous array
For most programs, the array-based stack is better. The linked list stack shines in real-time and functional programming contexts.
*Next Lesson: Stack Interview Problems — Balanced parentheses, daily temperatures, largest rectangle in histogram, and more.*
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Stack Using Linked List — Implementation, Analysis, and When to Use It.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Data Structures & Algorithms topic.
Search Terms
data-structures-algorithms, data structures & algorithms, data, structures, algorithms, stacks, stack, using
Related Data Structures & Algorithms Topics