Abstract Data Types (Array-Based)

Stack

A Last-In-First-Out (LIFO) structure built on an array — push, pop, peek, overflow and underflow checks, and a full exam-style question. The ADT behind Undo buttons, browser Back, and expression evaluation.

17.1 What is a Stack?

You already use stacks every day without naming them. When you stack plates after dinner, the last plate you put on top is the first one you take off. When you press Undo in a text editor, the most recent change is the one that gets reversed first. When you press Back in a browser, you return to the page you visited most recently. Every one of these follows the same rule: last in, first out (LIFO).

A stack is the computer-science name for that rule. It is an Abstract Data Type — a "shape" for data plus the operations allowed on it. The clever part is that your programming language does not give you a ready-made stack, so you build one yourself out of an array plus an integer pointer.

TermMeaning
StackAn ADT where items are added and removed at the same end (the top). LIFO.
LIFOLast In, First Out — the last item added is the first removed.
PushAdd a new item to the top of the stack.
PopRemove and return the item from the top.
TopPointerAn integer holding the index of the current top item. Moves up on push, down on pop.
OverflowTrying to push onto a full stack. A correct push must check for this.
UnderflowTrying to pop from an empty stack. A correct pop must check for this.
PeekLook at the top item without removing it. The pointer does not move.
Your Turn — Describe a stack [3 marks]
Describe two key features of a stack and state one situation where a stack would be a suitable choice.
Hint:
  • LIFO — last in, first out
  • Only access the top (push/pop at one end)
  • Use cases: Undo, Back button, expression evaluation
Your Turn
Describe two key features of a stack and state one situation, different from Undo, where a stack would be suitable.
Hint:
  • LIFO, single-end access
  • Browser Back button, or evaluating expressions

17.2 Setting Up the Stack

Python has no built-in "stack" type, so we build one from a list of a fixed size. We need three things:

  • MAX_SIZE — a constant saying how many items the stack can hold.
  • stack — the array (list) itself, sized to that constant.
  • top_pointer — an integer that says which index currently holds the top item.
MAX_SIZE = 5                       # the stack can hold 5 items
stack = [None] * MAX_SIZE          # the array that stores the data
top_pointer = -1                   # -1 means the stack is empty
Key rule — the empty value:
  • With 0-based array indexing, an empty stack is shown by top_pointer = -1.
  • When we push the first item it goes to index 0, and the pointer becomes 0.
Your Turn — Declare a stack of strings [3 marks]
Write code to declare a stack of 8 strings. Include MAX_SIZE, the array, and the pointer.
Hint:
  • MAX_SIZE = 8
  • Fill with "" (empty strings)
  • top_pointer = -1
Your Turn — Declare a stack of integers
Write code to declare a stack of 20 integers. Include MAX_SIZE, the array, and the pointer.
Hint:
  • Integers, so fill with 0 instead of ""
  • Same three-line pattern

17.2B Interactive Simulator

Try the stack yourself. Set MAX_SIZE, enter a value, and click Push or Pop. Watch the top_pointer climb and fall, and try to trigger overflow and underflow. Use the playback controls to step through the code.

Interactive Simulator

Stack

0
·
← EMPTY
1
·
2
·
3
·
4
·

Status: Push or Pop to start.

Code

1MAX_SIZE = 5
2if top_pointer == MAX_SIZE - 1:
3 print("Stack overflow")
4 top_pointer = top_pointer + 1
5 stack[top_pointer] = new_item
6if top_pointer == -1:
7 print("Stack underflow")
8 item = stack[top_pointer]
9 top_pointer = top_pointer - 1
10 return item

17.3 push() — Add to the Top

push() adds a new item to the top of the stack. The order is critical: check full → increment pointer → store item. Never store first then move the pointer, and never skip the full-check.

def push(new_item):
    global top_pointer
    if top_pointer == MAX_SIZE - 1:      # is the stack full?
        print("Stack overflow - cannot push")
    else:
        top_pointer = top_pointer + 1     # move the pointer up
        stack[top_pointer] = new_item       # store the item there
Key rule — push order:
  • Check full → increment pointer → store item.
  • Never store first then move the pointer, and never skip the full-check.
Your Turn — push with different name [5 marks]
A stack with constant MAX_SIZE and integer top_pointer already exists. Write a procedure push(new_item) that adds an item, or outputs a message if the stack is full.
Hint:
  • Check if full: top_pointer == MAX_SIZE - 1
  • If full: print message
  • Else: increment, store
  • Use global top_pointer
Your Turn — push(value) with different message
Write a push(value) that prints "Full" if the stack is full, otherwise adds the value.
Hint:
  • Same shape — only the parameter name and message change

17.4 pop() — Remove from the Top

pop() removes and returns the top item. The order is: check empty → read item → decrement pointer → return item. You must read the item BEFORE decrementing, or the pointer no longer points at it.

def pop():
    global top_pointer
    if top_pointer == -1:                  # is the stack empty?
        print("Stack underflow - nothing to pop")
        return None
    else:
        item = stack[top_pointer]            # read the top item
        top_pointer = top_pointer - 1       # move the pointer down
        return item                          # give it back to the caller
Key rule — read before decrement:
  • Read item = stack[top_pointer] FIRST, then top_pointer -= 1, then return item.
  • If you decrement first, the pointer no longer points at the item.
Exam tip:
  • Examiners give a mark for returning the popped value, not just removing it.
  • A pop that only lowers the pointer "loses" the data.
  • Read it into a variable before you decrement, then return that variable.
Your Turn — pop() with different message
Write a pop() that returns "Empty" if the stack is empty, otherwise removes and returns the top item.
Hint:
  • Check if empty: top_pointer == -1
  • If empty: return "Empty"
  • Else: read item, decrement, return item
Your Turn — undo() function
Write a function undo() that pops and returns the most recent action, or returns "Nothing to undo" if the stack is empty.
Hint:
  • Same as pop() — just a different name and empty message

17.5 peek(), is_empty(), is_full()

These three tiny helpers make push and pop readable. Writing if is_full(): instead of if top_pointer == MAX_SIZE - 1: reads like English and is harder to get wrong.

def is_empty():
    return top_pointer == -1

def is_full():
    return top_pointer == MAX_SIZE - 1

def peek():
    if is_empty():
        return None
    return stack[top_pointer]
Key rule — peek does not move the pointer:
  • peek() returns stack[top_pointer] without decrementing.
  • The item stays on the stack.
  • Only pop() moves the pointer.
Your Turn — size() function
Write a function size() that returns how many items are on the stack.
Hint:
  • If top_pointer = 2, there are 3 items (indices 0, 1, 2)
  • So size = top_pointer + 1
Your Turn — spaces_left() function
Write a function spaces_left() that returns how many free slots remain.
Hint:
  • Total slots minus items used
  • MAX_SIZE - (top_pointer + 1)

17.6 Tracing Push and Pop

A trace shows the stack state and top_pointer after each operation. Remember: push increments the pointer, pop decrements it.

# Trace: start empty, then push 7, push 3, pop, push 9

start    top_pointer = -1   stack = []
push 7   top_pointer = 0    stack = [7]
push 3   top_pointer = 1    stack = [7, 3]
pop      top_pointer = 0    (3 removed) -> returns 3
push 9   top_pointer = 1    stack = [7, 9]
Your Turn — Trace push/pop sequence
Trace: start empty, then push 4, push 8, push 2, pop, pop, push 5. What is top_pointer and what is on top?
Hint:
  • Pointer up on push, down on pop
  • push 4: tp=0 [4]
  • push 8: tp=1 [4,8]
  • push 2: tp=2 [4,8,2]
  • pop: tp=1 (2 gone)
  • pop: tp=0 (8 gone)
  • push 5: tp=1 [4,5]

17.7 Full Exam-Style Question

A text editor keeps the last few text changes on a stack so the user can undo them. The most recent change must be undone first. The stack can hold up to 10 changes.

(a) — Declare and initialise [3 marks]
  • The stack is stored as a global list changes with a global integer top.
  • Write program code to declare and initialise changes, top and a constant MAX set to 10.
Your Turn — (a) Model answer
Declare changes (size 10), top = -1, MAX = 10. [3 marks]
Hint:
  • Constant MAX = 10
  • List of size MAX
  • top = -1 (empty)
(b) — record(change) [6 marks]
  • Write a procedure record(change) that adds a change to the stack.
  • If the stack is full it must output "History full" and not add the change.
Your Turn — (b) Model answer
Write record(change) that pushes, or prints "History full" if full. [6 marks]
Hint:
  • Procedure header with parameter
  • global top
  • Full check: top == MAX - 1
  • Output "History full" and do not add
  • Else: increment top, store change
(c) — undo() [4 marks]
  • Write a function undo() that removes and returns the most recent change.
  • If there are no changes it returns "Nothing to undo".
Your Turn — (c) Model answer
Write undo() that pops and returns the most recent change, or "Nothing to undo". [4 marks]
Hint:
  • Empty check: top == -1
  • Return "Nothing to undo" if empty
  • Read item before decrementing
  • Decrement top, return item

Key Points Summary

A stack follows LIFO — Last In, First Out. The last item pushed is the first popped.
It is an Abstract Data Type (ADT) — data shape + operations, built from an array + pointer.
Two operations: push (add to top) and pop (remove from top).
Three setup items: MAX_SIZE constant, array of that size, top_pointer = -1 (empty).
top_pointer = -1 means empty. First push goes to index 0 (top_pointer = 0).
push order: check full → increment pointer → store item. Never skip the full check.
Overflow: top_pointer == MAX_SIZE - 1 (stack is full, cannot push).
pop order: check empty → read item → decrement pointer → return item.
Read the item BEFORE decrementing — otherwise the pointer no longer points at it.
Underflow: top_pointer == -1 (stack is empty, cannot pop).
pop() must RETURN the popped value, not just remove it.
peek() returns the top item WITHOUT moving the pointer.
is_empty(): top_pointer == -1. is_full(): top_pointer == MAX_SIZE - 1.
size() = top_pointer + 1. spaces_left() = MAX_SIZE - (top_pointer + 1).
Use cases: Undo, browser Back, expression evaluation, recursion call stack.
push and pop must use "global top_pointer" because they modify the pointer.

17.8 Practice Tasks

Fifteen exam-style stack tasks. Each shows only the question — click Hint for the thought process, or Help for the worked solution.

Exam tip:
  • For every stack task the marker checks:
  • (1) correct overflow/underflow check
  • (2) correct pointer movement (increment on push, decrement on pop — AFTER reading)
  • (3) correct storage/retrieval, and (4) returning the popped value
  • The most common mark loss is forgetting the full/empty check.
1Practice Task — Declare a stack [3 marks]
Write code to declare a stack of 5 items (None), with MAX_SIZE and top_pointer = -1.
2Practice Task — push() [5 marks]
Write push(new_item) that adds to the stack, or prints "Stack overflow" if full.
3Practice Task — pop() [5 marks]
Write pop() that removes and returns the top item, or prints "Stack underflow" and returns None if empty.
4Practice Task — peek() [3 marks]
Write peek() that returns the top item without removing it, or None if empty.
5Practice Task — is_empty() and is_full() [2 marks]
Write is_empty() and is_full() functions.
6Practice Task — size() [2 marks]
Write size() that returns how many items are on the stack.
7Practice Task — spaces_left() [2 marks]
Write spaces_left() that returns how many free slots remain.
8Practice Task — Trace push/pop [4 marks]
Trace: start empty, push 7, push 3, pop, push 9. Show top_pointer and stack after each.
9Practice Task — Trace longer sequence [4 marks]
Trace: push 4, push 8, push 2, pop, pop, push 5. What is top_pointer and what is on top?
10Practice Task — Describe a stack [3 marks]
Describe two key features of a stack and state one situation where it would be suitable.
11Practice Task — Overflow condition [2 marks]
What is the overflow condition for a stack, and what should push() do when it occurs?
12Practice Task — Underflow condition [2 marks]
What is the underflow condition for a stack, and what should pop() do when it occurs?
13Practice Task — Text editor undo [13 marks]
(a) Declare changes (10), top, MAX [3]. (b) record(change) with "History full" [6]. (c) undo() with "Nothing to undo" [4].
14Practice Task — Why read before decrement? [2 marks]
Explain why pop() must read the item into a variable BEFORE decrementing top_pointer.
15Practice Task — Stack vs queue [2 marks]
State one difference between a stack and a queue.

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

What rule does a stack follow?

Question 2True / False

TopPointer = -1 means the stack is empty.

Question 3Multiple Choice

What is the overflow condition?

Question 4Multiple Choice

What is the underflow condition?

Question 5True / False

In push(), you increment the pointer before storing the item.

Question 6Multiple Choice

In pop(), when do you read the item?

Question 7Multiple Choice

What does peek() do?

Question 8True / False

push() must declare "global top_pointer".

Question 9Multiple Choice

What does size() return?

Question 10Multiple Choice

Which is NOT a use case for a stack?

Question 11True / False

A stack is an Abstract Data Type (ADT).

Question 12Multiple Choice

What does spaces_left() return?

Answer all 12 questions to enable submission.