1. Data structures and the stack
A data structure is a way of organising data so it can be used efficiently (list, dictionary, stack, queue).
A stack is a linear structure with one open end, the top. Items are added (push) and removed (pop) only at the top, so the item added last is removed first: LIFO, Last In First Out. Everyday examples: a pile of plates or books, bangles on a wrist, the undo history of an editor.
| Structure | How items are added and removed | Everyday picture |
|---|---|---|
| List | At any position, by index | A numbered register |
| Stack | Only at one end, the top (LIFO) | A pile of plates |
| Queue | Added at the rear, removed from the front (FIFO) | A ticket-counter line |
| Dictionary | By key | A phone directory |
Key terms
- Data structure
An organised way of storing data so that it can be accessed and changed efficiently.
- Stack
A linear data structure where insertion and deletion happen at one end, the top.
- LIFO
Last In, First Out: the most recently added item is removed first.
2. Operations and a list implementation
| Operation | List code |
|---|---|
| Push x | stk.append(x) |
| Pop | stk.pop() (removes and returns the last item) |
| Peek / top | stk[-1] |
| Is empty | stk == [] or len(stk) == 0 |
| Size | len(stk) |
The end of the list is the top. Standard functions:
def push(stk, item):
stk.append(item)
def pop(stk):
if stk == []:
return "Underflow"
return stk.pop()
def peek(stk):
if stk == []:
return None
return stk[-1]
def is_empty(stk):
return stk == []
Running push twice and pop three times on a list of books gives Diary Diary Atlas Underflow: the third pop reports underflow.
| Operation | Meaning | With a list stk |
|---|---|---|
| Push | Add an item at the top | stk.append(x) |
| Pop | Remove and return the top item | stk.pop() |
| Peek (top) | Read the top item without removing it | stk[-1] |
| isEmpty | Is the stack empty? | stk == [] or len(stk) == 0 |
| Size | Number of items | len(stk) |
| Call | Result |
|---|---|
peek(books) | Diary |
pop(books) three times | Diary, Atlas, Underflow |
is_empty(books) | True |
Key terms
- Push
Adding an item at the top of the stack (append for a list).
- Pop
Removing and returning the top item (list pop with no argument).
- Peek
Reading the top item without removing it (index -1).
3. Underflow and overflow
Underflow: pop or peek on an empty stack. With a list, pop() on [] stops the program with IndexError: pop from empty list, so test if stk == []: first and report "Underflow" (then return, so the pop line is not reached).
Overflow: push on a full stack of fixed capacity, tested with len(stk) == capacity. A Python list grows as needed, so overflow does not occur in normal list programs; it matters when a size limit is set (a tray holder for four trays, the last 20 messages).
| Condition | When it happens | What the program does |
|---|---|---|
| Underflow | Pop or peek on an empty stack | Check stk == [] first; otherwise Python stops with IndexError: pop from empty list |
| Overflow | Push on a full fixed-size stack | Check len(stk) == capacity first; a plain Python list grows, so it does not overflow in normal use |
Key terms
- Underflow
An attempt to pop or peek from an empty stack.
- Overflow
An attempt to push onto a full stack of fixed size.
4. Displaying and tracing a stack
Display from the top down by counting the index down:
def display(stk):
if stk == []:
print("Stack is empty")
else:
for i in range(len(stk) - 1, -1, -1):
print(stk[i])
For [3, 8, 5] it prints 5, 8 and 3 on separate lines.
Tracing: write the stack as a list with the top on the right; push adds on the right, pop removes the rightmost item and returns it. Popped items always come out in reverse order of their pushes.
| i (from top) | Printed |
|---|---|
| 2 | 5 |
| 1 | 8 |
| 0 | 3 |
| Step | Operation | Stack (bottom → top) | Returned |
|---|---|---|---|
| 1 | push A | ['A'] | — |
| 2 | push B | ['A', 'B'] | — |
| 3 | pop | ['A'] | B |
| 4 | push C | ['A', 'C'] | — |
| 5 | push D | ['A', 'C', 'D'] | — |
| 6 | pop | ['A', 'C'] | D |
| 7 | pop | ['A'] | C |
Key terms
- Trace (dry run)
Following a program by hand and writing the stack after every operation.
5. Applications
- Reversing text, a list or the digits of a number: push all, pop all.
- Bracket matching: push opening brackets; for a closing one pop and compare; the stack must be empty at the end.
- Function calls: Python keeps active calls on a call stack; the latest call returns first.
- Undo and back buttons: push each action or page; undo or back pops the latest.
- Postfix evaluation: push numbers; an operator pops the right operand, then the left, and pushes the result.
4 5 + 2 *evaluates to 18. - Decimal to binary: push remainders of division by 2; popping gives the binary digits (11 gives 1011).
| Application | What is pushed | Why LIFO fits |
|---|---|---|
| Reversing text | Each character | The last character comes out first |
| Bracket checking | Each opening bracket | A closing bracket must match the latest open one |
| Function calls | Each active call | The latest call finishes first |
| Undo / Back | Each action or page | The latest action is undone first |
| Postfix evaluation | Each operand | An operator uses the two latest operands |
| Bracket read | Action | Stack after |
|---|---|---|
{ | push | { |
[ | push | {[ |
( | push | {[( |
) | pop ( matches | {[ |
] | pop [ matches | { |
} | pop { matches | empty |
end | stack empty |
| Token | Action | Stack after |
|---|---|---|
4 | push | [4] |
5 | push | [4, 5] |
+ | pop 5 and 4, push 9 | [9] |
2 | push | [9, 2] |
* | pop 2 and 9, push 18 | [18] |
Key terms
- Postfix expression
An expression in which each operator follows its two operands, such as 4 5 + for 4 + 5.
- Call stack
The stack Python uses to keep track of functions that have been called but not yet finished.
6. Board-style push and pop programs
A typical question gives a list or dictionary and asks for two functions:
- push: loop over the data, test the stated condition, and
appendthe items (or keys) that pass. - pop: loop while the stack is not empty, pop and display each item, then print the message asked for (such as "Stack Empty").
def push_cities(towns, stk):
for name, pin in towns.items():
if pin % 2 == 1 and len(name) > 4:
stk.append(name)
def pop_cities(stk):
while stk != []:
print(stk.pop(), end=" ")
print("| None left")
towns = {"Shimla": 171001, "Ooty": 643001, "Kohima": 797002, "Madurai": 625003, "Bhuj": 370001}
S = []
push_cities(towns, S)
print(S)
pop_cities(S)
Output:
['Shimla', 'Madurai']
Madurai Shimla | None left
| Town | PIN odd? | More than 4 letters? | Pushed? |
|---|---|---|---|
| Shimla | yes | yes | yes |
| Ooty | yes | no | no |
| Kohima | no | yes | no |
| Madurai | yes | yes | yes |
| Bhuj | yes | no | no |
Key terms
- Condition
The test in the question that decides which items are pushed.
Exam tips
Common mistakes
- Using
stk.push(x): lists have no push method; useappend. - Popping without checking for an empty stack (IndexError).
- Printing a "Underflow" message but not returning, so the pop still runs.
- Displaying the stack bottom first when the question asks for top first.
- Forgetting that popped items come out in reverse order.
- In postfix, popping the operands in the wrong order for
-and//.
How marks are usually awarded
- Output questions: each correct line or value as stated.
- Error-finding: ½ or 1 mark for each error found and corrected.
- Push/pop programs (3–5 marks): loop and condition, push, underflow check, pop loop with display, message.
- Theory: one point per mark, with an example.