Stack
Task: Push three values onto the stack
Why we need a Stack
Analogy
- In a canteen, clean plates are kept in a pile. A new plate is placed on the top. When someone needs a plate, they take the top one.
- Nobody pulls a plate out from the middle. The pile would fall over.
- So the plate kept last is the plate taken first. This simple pile is a stack. Everything below is just the technical vocabulary for it.
What is a stack
Definition
A stack is a linear data structure where you can add and remove items from one end only. That end is called the top.
The rule has a name: LIFO, Last In First Out. The item added most recently is the item removed first.
A queue follows the opposite rule, FIFO (First In, First Out), like a line at a ticket counter. If the oldest item should come out first, you need a queue, not a stack.
Only the top is open
This is the part beginners forget, so it is worth stating clearly.
A stack lets you
- add an item on the top
- remove the item from the top
- look at the top item
A stack does not let you
- read the 3rd item directly
- insert something in the middle
- search inside it without removing items
You give up access to the middle. In return, every operation stays very fast and very simple.
The operations
| Operation | What it does |
|---|---|
| push(x) | Puts x on the top |
| pop() | Removes the top item and returns it |
| peek() | Shows the top item without removing it |
| isEmpty() | Tells you if the stack has no items |
| size() | Tells you how many items are in it |
All five take O(1) time. That means the work stays the same whether the stack holds 10 items or 10 million. You are always touching only the top.
Out of these, only push and pop change the stack. The other three just read it.
Try it yourself
Last in, first out
Press pop() on an empty stack, or push() on a full one, and watch what the stack refuses to do. Both of those refusals have a name, further down the page.
In code
stack = [] stack.append(10) # pushstack.append(20) # push print(stack[-1]) # peek -> 20print(stack.pop()) # pop -> 20print(stack[-1]) # peek -> 10print(len(stack)) # size -> 1print(len(stack) == 0) # isEmpty -> FalseMost languages already give you a ready-made stack, so you rarely build one yourself:
- Python: a normal list with
append()andpop() - C++:
std::stack - Java:
ArrayDeque(preferred over the olderStackclass) - JavaScript: a normal array with
push()andpop()
Overflow and underflow
Two errors come up in almost every exam and interview.
Watch out
Stack overflow happens when you push into a stack that is already full. This applies to stacks built on a fixed-size array, and to the system call stack when a program goes too deep.
Stack underflow happens when you pop or peek an empty stack. There is no top plate to take.
One habit prevents half of these bugs: check isEmpty() before every pop.
How a stack is built
There are two common ways, and both keep all operations at O(1).
| Array based | Linked list based | |
|---|---|---|
| How it works | Keep an index called top. Push increases it, pop decreases it. | Add and remove nodes at the head of the list. |
| Size | Fixed, unless you use a resizable array | Grows as long as memory allows |
| Extra memory | None per item | One pointer per item |
For most beginner work, the array version is enough.
The stack your program is already using
This is the idea that makes stacks stick.
Every time a function is called, the computer creates a stack frame for it. The frame holds that function's local variables and the address to return to. That frame is pushed onto the call stack. When the function finishes, its frame is popped and control goes back to the caller.
This is why the function called last is always the one that finishes first.
It is also why endless recursion crashes with an error named after this very structure: stack overflow. The program keeps pushing frames and never pops any.
Note
So recursion is not a separate topic to learn. Recursion is a stack that the language manages for you.
Where stacks are used
- Undo (Ctrl+Z): every action is pushed, undo pops the most recent one
- Browser back button: visited pages are pushed, back pops the last one
- Bracket checking in compilers: making sure
{ [ ( ) ] }is written correctly - Expression evaluation: converting infix to postfix, and solving postfix
- DFS (Depth-First Search): using an explicit stack or recursion
- Backtracking: mazes, N-Queens, Sudoku. Push a choice, pop it when it fails
The pattern is easy to spot. A stack fits whenever you need to remember what you were doing just before this, and then step back out of it.
Worked example: balanced brackets
Input: { [ ( ) ] }
Rule: push every opening bracket. On a closing bracket, pop one and check that the pair matches. At the end, the stack must be empty.
| Read | Action | Stack after |
|---|---|---|
| { | push | { |
| [ | push | { [ |
| ( | push | { [ ( |
| ) | pop, ( matches | { [ |
| ] | pop, [ matches | { |
| } | pop, { matches | (empty) |
The stack is empty at the end, so the input is balanced.
The input is invalid if any of these happen:
- a pop gives a bracket that does not match
- a closing bracket arrives when the stack is empty
- the stack is not empty after reading everything
Try tracing { ( ] ) on paper. You will hit a mismatch at ].
When a stack is the wrong choice
Pick something else if:
- the oldest item should come out first, use a queue
- you need to read or search the middle, use an array or list
- you need the smallest or largest item quickly, use a heap
Ask one question before choosing: which item do I need next, the newest or the oldest? Newest means stack.
Common mistakes
- Popping without checking whether the stack is empty
- Mixing up
pop(removes the item) andpeek(does not remove it) - Using a stack where the order should be FIFO
- Expecting to reach the middle items
- In Python,
pop()removes from the top and is fast, butpop(0)removes from the front and is slow
Quick recap
- A stack is a pile. Last in, first out.
- Push and pop happen at the top only, and both are O(1).
- Popping an empty stack is underflow. Pushing a full one is overflow.
- Your own function calls run on a stack.
- Used in undo, browser history, bracket checking, DFS and backtracking.
Key takeaway
If you remember the pile of plates, you can rebuild this whole chapter from it.