Recursion
A function that calls itself. The concept that trips up most beginners — explained step by step, traced visually, and built up from the simplest example to the legendary Tower of Hanoi.
Quick answer
A recursive function solves a problem by calling itself on a smaller version of it until it reaches a base case it can answer directly. Each call gets its own frame on the call stack, which unwinds as results come back.
- Every recursion needs a base case, or it never stops.
- Each call must move closer to the base case.
- Too many nested calls overflow the stack.
#include <stdio.h>
long factorial(int n) {
if (n <= 1) return 1; /* base case */
return n * factorial(n - 1); /* smaller problem */
}
long hanoi_moves(int disks) {
if (disks == 0) return 0;
return 2 * hanoi_moves(disks - 1) + 1;
}
int main(void) {
printf("5! = %ld\n", factorial(5));
printf("moves for 3 disks = %ld\n", hanoi_moves(3));
return 0;
}Output
5! = 120 moves for 3 disks = 7
Recursion is one of those ideas that sounds impossible the first time you hear it. A function that calls itself? Does it not just loop forever? How does it ever stop? How does it know what to return?
These are exactly the right questions. By the end of this lesson every one of them will have a clear, satisfying answer. We will build the idea from a simple analogy, trace every call on the stack by hand, solve five classic problems, and understand why recursion is one of the most powerful tools in all of programming.
What is Recursion?
Recursion is when a function solves a problem by breaking it into a smaller version of the same problem and calling itself to solve that smaller version. It keeps breaking the problem down until it reaches a version so small it can be answered directly — without any further calls. That stopping point is called the base case.
🪞 The mirror analogy
Stand between two mirrors facing each other. You see yourself reflected, and inside that reflection you see another reflection, and inside that another — going smaller and smaller until they become too small to see.
Recursion works the same way. Each call creates a smaller version of itself, which creates an even smaller one, going deeper and deeper — until we hit the base case (the point where the mirrors end) and start coming back.
How Recursion Works Inside — The Call Stack
Remember the call stack from Lesson 7? When a function calls another function, the current function is paused and pushed onto the call stack. When the called function returns, the paused function resumes from where it stopped. Recursion uses this exact mechanism — but the function calls itself.
Recursion has two clear phases. Going down — each call pushes a new frame and makes the problem smaller. Coming back up — each call finishes and returns its answer to the call that made it. The final answer bubbles all the way back to the very first call.
factorial(3) — call stack at each stageProblem 1 — Factorial
Factorial of n (written as n!) means multiply all integers from 1 to n together. 5! = 5 × 4 × 3 × 2 × 1 = 120. And 0! = 1 by definition. This is the perfect first recursion problem because the pattern is obvious: n! = n × (n-1)!. The problem contains a smaller version of itself.
Problem 2 — Fibonacci
The Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21 ... Each number is the sum of the two before it. fib(n) = fib(n-1) + fib(n-2). Two base cases: fib(0) = 0 and fib(1) = 1.
⚠ Why this is dangerously slow
Computing fib(5) looks harmless — but look at how many times the same values get computed repeatedly:
├── fib(4)
│ ├── fib(3) ← computed again below
│ │ ├── fib(2)
│ │ └── fib(1)
│ └── fib(2) ← computed again below
└── fib(3) ← same as above, recomputed
├── fib(2) ← same again
└── fib(1)
Problem 3 — Sum of Digits
Given a number like 1234, find the sum of its digits: 1+2+3+4 = 10. The recursive insight: the sum of digits of 1234 = last digit (4) + sum of digits of 123. Keep peeling off the last digit until the number is 0.
= 4 + sumOfDigits(123)
= 4 + 3 + sumOfDigits(12)
= 4 + 3 + 2 + sumOfDigits(1)
= 4 + 3 + 2 + 1 + sumOfDigits(0)
= 4 + 3 + 2 + 1 + 0 ← base case
= 10 ✓
Problem 4 — Power (x to the n)
Computing x^n (x raised to the power n). The naive way: multiply x by itself n times — O(n). The recursive insight: x^n = x × x^(n-1). Base case: x^0 = 1. And with one small improvement we can make it O(log n) — the fast power trick.
Problem 5 — Greatest Common Divisor (GCD)
GCD of two numbers is the largest number that divides both of them exactly. GCD(12, 8) = 4. The Euclidean algorithm is one of the oldest algorithms in history — and it is naturally recursive. The insight: GCD(a, b) = GCD(b, a % b). Keep taking the remainder until b becomes 0. At that point, a is the GCD.
gcd(18, 12) → gcd(12, 18%12) = gcd(12, 6)
gcd(12, 6) → gcd(6, 12%6) = gcd(6, 0)
gcd(6, 0) → return 6 ← base case ✓
Recursion vs Iteration — When to Use Which
Every recursive solution can be rewritten as an iterative one (with loops), and vice versa. They are equally powerful. The choice depends on which makes the code clearer and more maintainable for a given problem.
Same problem — two solutions side by side
Tower of Hanoi — The Legendary Recursion Puzzle
Tower of Hanoi is the most famous recursion problem in all of computer science. It has three rods and n disks of different sizes stacked on the first rod — largest at the bottom, smallest at the top. The goal: move all disks to the third rod.
Step 1 and Step 3 are the recursive calls — the same problem on n-1 disks. Step 2 is the base work. When n = 1 (just one disk), move it directly — that is the base case. The magic: you never need to think about which specific disk goes where. Just trust the three steps — recursion handles all the details.
Errors You Will Hit
You Are Ready for Lesson 10
You now understand recursion completely — the base case, recursive case, how the call stack manages each frame, and why some recursive solutions are dangerously slow. You traced factorial, Fibonacci, sum of digits, power, GCD, and the legendary Tower of Hanoi.
In Lesson 10 we cover Sorting Algorithms — six different ways to arrange data in order, from the simplest to the fastest. Bubble sort, selection sort, insertion sort, merge sort, quick sort, counting sort. Each explained with step-by-step visuals and full C code.
🎯 Key Takeaways
- ✓Recursion = a function that calls itself on a smaller version of the problem until it hits a base case
- ✓Two laws: base case (where it stops) and recursive case (must move closer to base case each call)
- ✓The call stack manages recursion automatically — each call gets its own frame, frozen until it returns
- ✓Recursion has two phases: going down (building up calls) and coming back up (returning answers)
- ✓Factorial: n! = n × (n-1)! — base case n=0 returns 1
- ✓Fibonacci naive is O(2ⁿ) because it recomputes the same values — fixed by Dynamic Programming in Lesson 17
- ✓Fast power uses divide-and-conquer to compute x^n in O(log n) instead of O(n)
- ✓GCD(a, b) = GCD(b, a%b) — keep taking remainder until b=0, then a is the answer
- ✓Tower of Hanoi: move n-1 to helper, move largest to target, move n-1 to target — O(2ⁿ) moves
- ✓Always write base case first. Always return the recursive call result. Always move toward the base case
Quick check
What happens if a recursive function has no base case?
HELP US IMPROVE
How was this lesson?
Your note is shared with the Chaduvuko team for review. Please don’t include personal or sensitive information.
Spotted a mistake or something unclear? Suggest a fix on GitHub or email us. Select the text first and it is quoted for you.
Discussion
0Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.
