31.1 What is Recursion? The Factorial Problem
You have already met two ways of repeating work — FOR loops and WHILE loops. Recursion is a third way of repeating work, but it does not use a loop at all. Instead, a function or procedure calls itself with a smaller version of the same problem, and keeps doing so until the problem is small enough to be solved directly.
- You already know that
5!means5 × 4 × 3 × 2 × 1 = 120. - The factorial problem is the simplest possible example that defines itself in terms of itself:
5!is just5 × 4!. - Once you see why that single observation gives you a complete algorithm, you understand recursion.
Factorial(n) = n × Factorial(n − 1)for anyn > 0, andFactorial(0) = 1.- The first part is the general case, the second part is the base case.
| Term | Meaning |
|---|---|
| Recursion | A method where a function or procedure calls itself, with each call working on a smaller version of the same problem. |
| Base case | The simplest version of the problem, which can be answered directly without calling the function again. Recursion stops here. |
| General case | The case where the function calls itself with a smaller input. Sometimes called the recursive step. |
| Recursive call | The line inside the function where it calls itself again, passing a smaller value. |
| Call stack | An area of memory where the computer keeps each unfinished function call. New calls are pushed on top; finished ones are popped off. |
| Stack frame | One entry on the call stack. It holds the parameters, local variables, and the return address for one call. |
| Unwinding | The phase after the base case is reached, where each call returns its value to the call that made it, one by one. |
| Stack overflow | An error that happens when too many calls are pushed onto the call stack — usually because the base case is missing or never reached. |
| Iteration | Repeating work using a loop (FOR, WHILE, REPEAT). The non-recursive alternative. |
Iterative (loop) version:
FUNCTION Factorial(n : INTEGER) RETURNS INTEGER
DECLARE result : INTEGER
result <- 1
FOR i <- 1 TO n
result <- result * i
NEXT i
RETURN result
ENDFUNCTIONRecursive version:
FUNCTION Factorial(n : INTEGER) RETURNS INTEGER
DECLARE result : INTEGER
IF n = 0 THEN
result <- 1 // BASE CASE
ELSE
result <- n * Factorial(n - 1) // GENERAL CASE + RECURSIVE CALL
ENDIF
RETURN result
ENDFUNCTIONThe recursive version has no loop. Notice the line result ← n * Factorial(n - 1) — the function calls itself with a smaller value. The function reads almost exactly like the mathematical formula n × (n − 1)!. Without the base case, the function would call itself forever and the call stack would overflow.
- Each box is one call. A box can only finish once the box <em>inside</em> it has finished.
- The calling phase goes outside-in; the green inner box is the base case.
- Once it returns 1, the answers flow back outward (unwinding): 1 → 1 → 2 → 6 → 24.
- Step 1 — Track each call as it happens (calling phase): Fact(4)→Fact(3)→Fact(2)→Fact(1)→Fact(0).
- Step 2 — Reach the base case: Fact(0) returns 1.
- Step 3 — Unwind: each paused call multiplies and returns (1→1→2→6→24).
- The calling phase has 6 rows (n = 5, 4, 3, 2, 1, 0). Then unwinding starts from the base case and works back out, multiplying each time.
- When Cambridge asks you to trace a recursive function, always lay out two phases: a calling phase where each row shows the call and the expression that is waiting, then a clearly marked unwinding phase where return values appear in reverse order.
- Examiners award one mark for reaching the base case and one mark for the final returned value, with intermediate marks for correct return values during unwinding.
31.1 What is Recursion? The Factorial Problem
31.2 Essential Features of Recursion
- Cambridge exam questions on recursion very often start with: “State the essential features of a recursive routine” or “Identify three features of recursion shown by this algorithm”.
- These are AO1 knowledge marks — easy to score if you have the list memorised.
Any recursive routine — no matter the problem it solves — must have all four of the following features. Miss one and the routine will either fail to stop, fail to produce an answer, or fail to be recursive at all.
| # | Feature | What it means |
|---|---|---|
| 1 | Base case | A condition that can be solved directly without another recursive call. This is the stopping condition. |
| 2 | General case | The case where the routine calls itself, expressing the answer in terms of a smaller version of the problem. |
| 3 | Recursive call | The line inside the routine where it calls itself, passing a value closer to the base case. |
| 4 | Progress to base case | Each recursive call must move the input closer to the base case. Otherwise the routine never stops. |
- No base case → the function calls itself forever and the call stack overflows.
- No general case → the function is not recursive; it is just a regular function.
- No progress toward base case → e.g. calling
Factorial(n)from insideFactorial(n). Again, infinite recursion and stack overflow.
- Step 1 — Find the base case (IF n = 0).
- Step 2 — Find the general case and recursive call (ELSE, CALL CountDown(n-1)).
- Step 3 — Check progress (n-1 moves toward 0).
- Look for (1) a condition that returns an answer with no further call, (2) a branch with a self-call, (3) something that decreases on each call.
- When the question says “identify” or “state” the features, you do not need long sentences.
- One-line bullet points with the keyword (
base case,general case,recursive call,progress) and a quoted line from the code are enough. - Examiners want to see the keyword and evidence that you can locate it in the supplied code.
31.2 Essential Features of Recursion
31.3 Tracing Recursive Algorithms
- Tracing recursion is one of the most common AO2 questions on Paper 3.
- The examiner gives you a small recursive function with a starting value and asks for the output, the return value, or both.
- Students lose marks because they try to do it in their head.
- The fix: always draw a two-phase trace table — calling phase, then unwinding phase.
- Write the initial call as the first row of a table.
- For each row, check the base case condition. If FALSE, write the expression that will be returned (with the recursive call still inside it) and add a new row for the recursive call.
- When the base case becomes TRUE, write down the return value and draw a line to mark where unwinding starts.
- Work back up the table. For each paused call, substitute the return value from the call below into its expression and evaluate.
- Calling phase: each call where n > 0 pauses, waiting for the next call to return.
- Unwinding: substitute each return value back into the call above.
- This is a procedure, not a function — there is no return value. Each call outputs either n or “Blast off!”.
- Pay close attention to where the recursive call sits in the code.
- If the call comes before any output, the outputs appear during unwinding and are in reverse order.
- If the call comes after any output (as in
CountDown), the outputs happen during the calling phase and are in natural order. - Students who do not check this routinely produce the right numbers in the wrong order.
31.3 Tracing Recursive Algorithms
31.4 More Recursive Examples
- Factorial is the textbook example, but examiners deliberately pick problems you have not seen before.
- This section gives you two more recursive patterns — converting a denary number to binary, and counting digits — so that when an unfamiliar recursive routine appears in the exam, you already know how to read it.
Example 1 — Denary to binary by repeated division:
The last bit of n in binary is n MOD 2. The rest of the bits are the binary of n DIV 2. So the binary of n is DenaryToBinary(n DIV 2) with n MOD 2 stuck on the end. The base case is when n = 0 — return the empty string.
FUNCTION DenaryToBinary(n : INTEGER) RETURNS STRING
DECLARE result : STRING
IF n = 0 THEN
result <- ""
ELSE
result <- DenaryToBinary(n DIV 2) & NUM_TO_STR(n MOD 2)
ENDIF
RETURN result
ENDFUNCTION- At each call, compute n DIV 2 (the next n) and n MOD 2 (the bit collected). Unwind by appending each bit.
- Keep dividing by 2. The base case is n = 0. Each n MOD 2 is the bit collected; the final string is read from the last call back up to the first.
Example 2 — Counting the digits in a positive integer:
The base case is a single-digit number (less than 10) — it has 1 digit. Otherwise, the answer is 1 + CountDigits(n DIV 10) (chop off the last digit).
FUNCTION CountDigits(n : INTEGER) RETURNS INTEGER
IF n < 10 THEN
RETURN 1
ELSE
RETURN 1 + CountDigits(n DIV 10)
ENDIF
ENDFUNCTION
// CountDigits(4729):
// CountDigits(4729) = 1 + CountDigits(472)
// CountDigits(472) = 1 + CountDigits(47)
// CountDigits(47) = 1 + CountDigits(4)
// CountDigits(4) = 1 <- base case, 4 < 10
// Unwinding: 1 -> 2 -> 3 -> 4- Whenever a problem can be phrased as “the answer for
nis some-operation-of(n) combined with the answer for a-smaller-version-of-n”, recursion will work. - The exam will not ask you to design a recursive routine from scratch on Paper 3 — but it will ask you to complete or trace one.
31.4 More Recursive Examples
31.5 Recursion vs Iteration
- Anything that can be done recursively can also be done with a loop, and vice versa.
- So why bother with recursion at all?
- Cambridge questions ask you to compare the two approaches and to justify when each is appropriate.
| Recursion — strengths | Recursion — weaknesses |
|---|---|
| Code matches the mathematical or natural definition (e.g. factorial, Fibonacci). | Each call uses memory on the call stack — risk of stack overflow for deep recursion. |
| Often shorter and more readable for problems with self-similar structure. | Slower because every call has overhead (saving and restoring stack frames). |
| Natural fit for recursive data structures: binary trees, linked lists, file directories. | Harder for beginners to trace and debug. |
| Useful for divide-and-conquer algorithms (binary search, merge sort, quicksort). | The same sub-problem may be solved many times (e.g. naive Fibonacci). |
| Iteration — strengths | Iteration — weaknesses |
|---|---|
| Uses only one stack frame — no risk of stack overflow. | Code can be longer and less elegant for problems with self-similar structure. |
| Faster: no function-call overhead per step. | Awkward fit for processing trees and other branching data (a stack must be managed by hand). |
| Lower memory use overall. | Some divide-and-conquer algorithms become much harder to express. |
| Easier to trace step by step using a standard trace table. | — |
- Use recursion when the problem is self-similar (factorial, Fibonacci, tree traversal, divide-and-conquer).
- Use iteration when repetitions are simple and bounded (looping through an array, totalling values, counting).
- The safest line: “Recursion is beneficial when the problem has a recursive structure; otherwise, iteration is usually faster and uses less memory.”
- Think about what changes: memory (stack frames), speed (call overhead), stack overflow risk, traceability.
- Think about how a binary tree is built (each node has subtrees) and how that matches a routine that calls itself on each subtree.
- When asked to “compare” or “give advantages and disadvantages”, do not write vague things like “recursion is more elegant” — that earns nothing.
- State the technical reason: memory, stack frames, execution speed, stack overflow, code length, matching a recursive data structure.
- One technical reason equals one mark.
31.5 Recursion vs Iteration
31.6 Compiler & Stack — How Recursion Really Runs
- Cambridge specifically lists “use of stacks and unwinding” in the syllabus.
- Examiners ask you to explain what the compiler does when a recursive routine runs — and the answer is always the same: it uses a stack to remember each paused call.
When any function or procedure is called, the computer needs to remember three things so it can resume the calling code afterwards: the values of the parameters passed in, the local variables created inside the function, and the return address — where in the calling code to come back to. This bundle is called a stack frame. The compiler pushes a new stack frame onto the call stack every time a function is called, and pops it off again when the function returns. For a recursive call, several frames pile up — one per pending call.
- Push a new stack frame containing the current parameter, any local variables, and the return address.
- Execute the body of the function with the new parameter.
- If the base case is met, calculate the return value.
- If not, push another frame and repeat from step 1.
- When a function returns, pop its frame off the stack and pass the return value back to the call that was waiting (unwinding).
- Step 1 — On each call, a frame is pushed (parameter, local vars, return address).
- Step 2 — Base case provides the first real return value (frame popped).
- Step 3 — Unwinding pops one frame at a time, passing values back.
- Think about what a missing base case does — what stops the pushing?
- Examiners reward the specific vocabulary: stack frame, pushed onto the stack, popped off, base case, unwinding, return address.
- Use these exact words.
- A vague answer like “the program remembers each call and reverses them at the end” is unlikely to score full marks, even if the meaning is right.
31.6 Compiler & Stack
31.7 Full Exam-Style Questions
Q1 (a) [2] Define the term recursion. (b) [2] State two essential features that every recursive routine must contain.
Q2 (a) [1] A function Mystery is defined as Mystery(n) = Mystery(n-1) + Mystery(n-2) with base case n ≤ 1 returns n. State the value returned by Mystery(4). (b) [1] State the sequence for arguments 0, 1, 2, 3, 4, 5. (c) [1] State the name commonly given to this sequence.
Q3 (a) [2] PrintReverse(n) outputs n MOD 10 then, if n ≥ 10, calls PrintReverse(n DIV 10). State the output of PrintReverse(347). (b) [1] Identify the base case. (c) [2] Explain why the output is in reverse order.
Q4 (a) [4] Describe how a compiler uses a stack to handle a recursive function. Refer to the call stack, stack frames, and unwinding. (b) [2] Explain what is meant by a stack overflow and one reason why a recursive function might cause one.
- Q1: recursion = calls itself with smaller problem until base case; features = base case + general case + progress.
- Q2: Mystery(4) = 3; sequence = 0,1,1,2,3,5; Fibonacci.
- Q3: output 7 4 3; base case n < 10; reverse because OUTPUT comes before the recursive call.
- Q4: push frame per call (params, locals, return addr); base case returns; pop + unwind; stack overflow = too many frames, no base case or no progress.
✓ Key Points Summary
31.8 Practice Tasks
Fifteen exam-style tasks. Click Hint for bullet-point guidance, then Help to reveal a worked solution.
Question Bank
Answer all questions, then press Submit Quiz to see your score.
Question 1Multiple Choice
Recursion is:
Question 2Multiple Choice
The base case of a recursive routine is:
Question 3True / False
Every recursive routine must have a base case, a general case, a recursive call, and progress toward the base case.
Question 4Multiple Choice
Factorial(4) returns:
Question 5Multiple Choice
What are the two phases of a recursive trace?
Question 6Multiple Choice
SumTo(4) returns: (SumTo(n) = n + SumTo(n-1), SumTo(0) = 0)
Question 7True / False
If the recursive call comes before the output, outputs appear in reverse order during unwinding.
Question 8Multiple Choice
DenaryToBinary(13) returns:
Question 9Multiple Choice
CountDigits(4729) returns: (base: n < 10 returns 1; else 1 + CountDigits(n DIV 10))
Question 10Multiple Choice
A weakness of recursion vs iteration is:
Question 11Multiple Choice
What is a stack frame?
Question 12True / False
A stack overflow occurs when too many calls are pushed onto the call stack — usually because the base case is missing or never reached.
Answer all 12 questions to enable submission.