✓ Free · Component 2 · 2.3.1 Algorithms
2.3.1a Stacks, Queues and Complexity
OCR H446 · A Level Computer Science · ~20 min read
Notes
Video
Slides
Worksheet
Quiz

Abstract Data Types (ADTs)

An Abstract Data Type (ADT) defines a data structure by its behaviour (operations and their effects) rather than its implementation. The user only needs to know WHAT the ADT does — not HOW it stores data internally. Two fundamental ADTs: the stack and the queue.

Stacks

A stack is a LIFO (Last In, First Out) data structure. Think of a stack of plates — you can only add or remove from the top. Elements are pushed onto the top and popped from the top.

Stack Operations

OperationDescriptionTime
push(item)Add item to the top of the stackO(1)
pop()Remove and return the top itemO(1)
peek() / top()Return the top item WITHOUT removing itO(1)
isEmpty()Return True if stack is emptyO(1)
isFull()Return True if stack is at capacity (if bounded)O(1)
size()Return number of elements in stackO(1)

Stack Errors

Stack overflow: pushing onto a full stack. Stack underflow: popping from an empty stack. Both must be handled (check isEmpty/isFull before operations). In recursion, stack overflow occurs when recursion depth exceeds the call stack size — every function call uses stack space.

Stack Implementation in Pseudocode

// Stack using an array + top pointer
stack ← [] (empty array, max size MAX)
top ← -1   // -1 = empty

function push(item)
    if top = MAX - 1 then
        print("Stack overflow!")
    else
        top ← top + 1
        stack[top] ← item
    endif
endfunction

function pop()
    if top = -1 then
        print("Stack underflow!")
    else
        item ← stack[top]
        top ← top - 1
        return item
    endif
endfunction

function peek()
    if top = -1 then return None
    return stack[top]
endfunction

function isEmpty()
    return top = -1
endfunction

Stack Applications

  • Call stack: each function call creates a new stack frame (local variables, return address); returning pops the frame. Recursion uses the call stack deeply.
  • Undo operations: text editor undo stores previous states on a stack; Ctrl+Z pops the most recent state.
  • Expression evaluation: converting infix (3+4) to postfix (3 4 +) and evaluating using stacks (Shunting-yard algorithm).
  • DFS (Depth-First Search): iterative DFS uses an explicit stack (or the call stack for recursive DFS).
  • Bracket matching: push each opening bracket; when closing bracket found, pop and check it matches.
  • Backtracking: maintain a stack of states to explore.

Queues

A queue is a FIFO (First In, First Out) data structure. Think of a supermarket queue — people join at the back (enqueue) and are served from the front (dequeue).

Queue Operations

OperationDescriptionTime
enqueue(item)Add item to the rear (back) of the queueO(1)
dequeue()Remove and return item from the frontO(1)
front() / peek()Return the front item without removing itO(1)
isEmpty()Return True if queue is emptyO(1)
size()Return number of elementsO(1)

Circular Queue

A circular queue (ring buffer) uses a fixed-size array with two pointers: front and rear. When the rear reaches the end of the array, it wraps around to index 0. This avoids wasting space from elements removed at the front.

// Circular queue with size MAX
queue ← array of size MAX
front ← 0
rear ← -1
count ← 0

function enqueue(item)
    if count = MAX then print("Queue full")
    else
        rear ← (rear + 1) MOD MAX    // wrap around
        queue[rear] ← item
        count ← count + 1
    endif
endfunction

function dequeue()
    if count = 0 then print("Queue empty")
    else
        item ← queue[front]
        front ← (front + 1) MOD MAX  // wrap around
        count ← count - 1
        return item
    endif
endfunction

Priority Queue

A priority queue is a variant where each element has a priority. Higher-priority elements are dequeued before lower-priority ones, regardless of arrival order. Implemented using a heap (O(log n) enqueue/dequeue). Used in Dijkstra's algorithm — always process the unvisited node with smallest distance first.

Queue Applications

  • BFS (Breadth-First Search): nodes are enqueued and explored level by level.
  • OS process scheduling: processes waiting for CPU time are held in a queue; the scheduler dequeues and runs them.
  • Print spooler: documents queued in order; printer processes FIFO.
  • Keyboard buffer: keystrokes stored in queue; processed in order.
  • Network packet handling: packets queued at routers and processed in order.

Algorithm Complexity for ADT Operations

OperationStackQueuePriority Queue (heap)
Insert (push/enqueue)O(1)O(1)O(log n)
Remove (pop/dequeue)O(1)O(1)O(log n)
Peek/frontO(1)O(1)O(1)
Search (contains)O(n)O(n)O(n)
Size/isEmptyO(1)O(1)O(1)

Stack and queue operations are all O(1) (constant time) for the core push/pop/enqueue/dequeue operations — because they always add/remove from a fixed end. This is a key advantage over arrays (where inserting at a specific position is O(n)).

Exam tip: LIFO → Stack; FIFO → Queue. Learn the applications: call stack → stack; BFS → queue; DFS → stack; OS scheduling → queue; undo → stack; print spooler → queue. These come up frequently in exam questions.
Exam tip: For circular queues, the wrap-around formula is: rear ← (rear + 1) MOD MAX. Know why circular queues solve the "false full" problem of linear queues — when front pointer moves forward, that space is reused.
✓ Notes completed!
Video coming soon
Click to advance · Arrow keys also work
Click slide or press arrow keys to navigate

Worksheet — 2.3.1a Stacks, Queues & Complexity

8 questions · 24 marks · instantly marked

Q1Explain the difference between a stack and a queue. State the access order for each and give a real-world analogy for each.[4 marks]
✓ Mark scheme
Stack: LIFO (Last In, First Out) — the most recently added item is the first to be removed [1]. Real-world analogy: stack of plates (take from top, add to top) OR browser back button [0.5]. Queue: FIFO (First In, First Out) — the first item added is the first to be removed [1]. Real-world analogy: supermarket checkout queue, or print spooler [0.5]. Key difference: stacks access at one end only; queues add at rear and remove from front [1].
Q2Trace the following stack operations and state the stack contents after each operation. Start with an empty stack:
push(5), push(3), push(8), pop(), push(2), peek()
[3 marks]
✓ Mark scheme
push(5): [5] — top=5 [0.5]
push(3): [5, 3] — top=3 [0.5]
push(8): [5, 3, 8] — top=8 [0.5]
pop(): removes 8, returns 8, stack=[5, 3] — top=3 [0.5]
push(2): [5, 3, 2] — top=2 [0.5]
peek(): returns 2, stack=[5, 3, 2] (unchanged — peek does NOT remove) [0.5]
Q3Describe what happens when you pop() from an empty stack. What is this called and how should it be handled?[2 marks]
✓ Mark scheme
This is called stack underflow [1]. It occurs when attempting to pop() from a stack that contains no elements (top = -1 / isEmpty() is True). It should be handled by checking isEmpty() before calling pop() — if empty, raise an exception (e.g. StackUnderflowError) or return an error/None value rather than attempting to access an invalid index [1].
Q4Give three different applications of a stack and explain the role of the stack in each.[3 marks]
✓ Mark scheme
Any 3, 1 mark each: Call stack — each function call pushes a frame (local variables, return address) onto the stack; returning pops the frame, restoring the previous execution context [1]. Undo in text editors — each editing action is pushed; pressing Ctrl+Z pops the most recent action and reverts it [1]. DFS (Depth-First Search) — a stack stores nodes to visit; pop a node, process it, push its neighbours (iterative DFS) [1]. Expression evaluation / bracket matching — opening brackets pushed; closing brackets trigger a pop and match [1]. Backtracking in algorithms — stack stores decision points to revisit [1].
Q5Explain what a circular queue is and why it is preferred over a simple linear queue implemented on an array.[3 marks]
✓ Mark scheme
A circular queue uses a fixed-size array with front and rear pointers that wrap around using modulo arithmetic: (rear + 1) MOD MAX [1]. Problem with simple linear queue: when elements are dequeued, the front pointer moves forward. Eventually, even though array slots at the front are free, the rear pointer can't advance past the end — a "false full" condition. The free space at the front is wasted [1]. Circular queue solution: when rear reaches the end, it wraps to index 0 (using MOD), reusing the freed slots at the front. The queue is truly full only when count = MAX — all slots occupied [1].
Q6What is a priority queue? How does it differ from a standard FIFO queue? Give one application.[3 marks]
✓ Mark scheme
Priority queue: each element has an associated priority value [1]. Unlike FIFO (where order is strictly arrival order), a priority queue dequeues the highest-priority element first, regardless of when it arrived [1]. Application: Dijkstra's algorithm — always processes the unvisited node with the smallest tentative distance (priority) first. OR OS process scheduling with priorities — high-priority processes jump the queue [1].
Q7State the time complexity of push, pop, and peek on a stack. Justify your answers.[3 marks]
✓ Mark scheme
Push: O(1) — adds to the top of the stack (updates top pointer and assigns one array element). Number of operations is constant regardless of stack size [1]. Pop: O(1) — removes from the top (reads top element, decrements top pointer). Always the same one operation regardless of stack size [1]. Peek: O(1) — reads the top element (stack[top]) without modifying anything. No iteration required [1]. All stack operations targeting the top are O(1) because the top pointer always tracks the current top element directly.
Q8Describe how a queue is used in BFS (Breadth-First Search). Why is a queue appropriate here, and why not a stack?[3 marks]
✓ Mark scheme
BFS: start by enqueuing the start node; repeat: dequeue the front node, process it, enqueue all unvisited neighbours; until queue empty [1]. A queue is appropriate because BFS must explore all nodes at distance k before any node at distance k+1 — FIFO ensures nodes are processed in the order they were discovered (level-by-level) [1]. A stack (LIFO) would produce DFS — always going as deep as possible along one path before backtracking. Using a stack for BFS would not give level-by-level traversal and would NOT find shortest paths [1].
Topic Quiz
1 of 15
You scored
out of 15
🎯

Mini Test — 2.3.1a Stacks, Queues & Complexity

  • 10 questions · 10 marks · 10 minutes
  • 5 MCQ + 5 short answer
Card 1 of 15
Click to reveal
🎉
Complete!
TermDefinition
← 2.2.1f Modular Design & Algorithms 2.3.1 Algorithms Next: 2.3.1b Linear & Binary Search →