C++: Recursion

Last updated: 2026-08-26

Recursion is a function calling itself.

Sounds strange — how can a function call itself? Won't it loop forever?

As long as you write a proper "exit condition," recursion works correctly — and can solve many problems that are hard to write with loops.



1. What is Recursion?

(1) 1.1 Recursion in Everyday Life

Real-life Analogy Recursive Characteristic
Two mirrors facing each other, reflecting each other's image Calling itself
Russian nesting dolls (open one, there's another inside) Breaking a problem into a smaller version of the same problem

Core idea of recursion: Break a big problem down into smaller problems of the same type, until the problem is small enough to solve directly.

(2) 1.2 Two Conditions for Recursion

Every recursive function must have:

  1. Base Case: The condition for exiting recursion (the simplest case)
  2. Recursive Case: Breaking the problem into smaller problems of the same type


2. Recursion Example: Factorial

(1) 2.1 Definition of Factorial

TEXT 📖 Display only
n! = n × (n-1) × (n-2) × ... × 1

Recursive definition:

TEXT 📖 Display only
n! = n × (n-1)! (recursive case)
0! = 1 (base case)

▶ Example 1: Calculating Factorial with Recursion (Difficulty ⭐⭐)

CPP
#include <iostream>

// Recursive function:Calculate n factorial
long long factorial(int n) {
 // Base case
 if (n == 0) {
 return 1;
 }
 // Recursive case
 return n * factorial(n - 1);
}

int main() {
 int n;
 std::cout << "Please enter a non-negative integer: ";
 std::cin >> n;
 
 std::cout << n << "! = " << factorial(n) << std::endl;
 
 return 0;
}
▶ Try it Yourself

Output:

TEXT 📖 Display only
Please enter a non-negative integer: 
! = 

Running result:

TEXT 📖 Display only
Please enter a non-negative integer: 5
5! = 120

(2) 2.2 Recursive Call Process (n=5)

TEXT 📖 Display only
factorial(5)
= 5 × factorial(4)
= 5 × 4 × factorial(3)
= 5 × 4 × 3 × factorial(2)
= 5 × 4 × 3 × 2 × factorial(1)
= 5 × 4 × 3 × 2 × 1 × factorial(0)
= 5 × 4 × 3 × 2 × 1 × 1 ← base case reached, starts returning
= 5 × 4 × 3 × 2 × 1
= 5 × 4 × 3 × 2
= 5 × 4 × 6
= 5 × 24
= 120

💡 Key point: During a recursive call, the function pauses at the line return n * factorial(n-1);, waiting for factorial(n-1) to return its result, then calculates n * result.



3. Recursion Example: Fibonacci Sequence

(1) 3.1 Definition of the Fibonacci Sequence

TEXT 📖 Display only
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) (n ≥ 2)

Sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, ...

▶ Example 2: Calculating Fibonacci Numbers with Recursion (Difficulty ⭐⭐)

CPP
#include <iostream>

int fibonacci(int n) {
 // Base case
 if (n == 0) {
 return 0;
 }
 if (n == 1) {
 return 1;
 }
 // Recursive case
 return fibonacci(n - 1) + fibonacci(n - 2);
}

int main() {
 int n;
 std::cout << "Please enter a non-negative integer: ";
 std::cin >> n;
 
 std::cout << "F(" << n << ") = " << fibonacci(n) << std::endl;
 
 return 0;
}
▶ Try it Yourself

Output:

TEXT 📖 Display only
Please enter a non-negative integer: 
F() = 

Running result:

TEXT 📖 Display only
Please enter a non-negative integer: 10
F(10) = 55

💡 Tip: This recursive implementation is very inefficient (it recalculates many values repeatedly). Later you'll learn how to optimize it with loops or memoization.



4. Recursion vs Loops

(1) 4.1 Comparison

Comparison Recursion Loops
Code simplicity ⭐⭐⭐⭐⭐ (more intuitive for certain problems) ⭐⭐⭐
Efficiency ⭐⭐ (function call overhead) ⭐⭐⭐⭐⭐
Memory usage High (each recursive call uses stack space) Low
Use cases Naturally recursive problems (e.g., trees, graphs) Most scenarios

(2) 4.2 Rewriting Factorial with a Loop

CPP
#include <iostream>

long long factorial(int n) {
 long long result = 1;
 for (int i = 1; i <= n; i++) {
 result *= i;
 }
 return result;
}

int main() {
 int n;
 std::cout << "Please enter a non-negative integer: ";
 std::cin >> n;
 
 std::cout << n << "! = " << factorial(n) << std::endl;
 
 return 0;
}

💡 Advice: If a problem can be easily solved with a loop, prefer loops. Recursion is suited for problems that are "naturally recursive" (e.g., tree traversal, quicksort).



5. The Pitfall of Recursion: Stack Overflow

(1) 5.1 What is Stack Overflow?

Every function call takes up space on the call stack. If recursion goes too deep (e.g., tens of thousands of levels), the call stack runs out, causing a Stack Overflow.

CPP
#include <iostream>

void infiniteRecursion() {
 infiniteRecursion(); // ❌ No base case, infinite recursion
}

int main() {
 infiniteRecursion();
 return 0;
}

Running result:

TEXT 📖 Display only
Segmentation fault (core dumped) // Linux

Or

CPP
Process finished with exit code -1073741571 // Windows: stack overflow

(2) 5.2 How to Avoid Stack Overflow?

  1. Ensure there is a base case, and that the base case can definitely be reached
  2. Control recursion depth (e.g., rewrite with a loop)
  3. Use tail recursion optimization (covered later, but not all compilers support it)


6. Practice: Tower of Hanoi

▶ Example 3: Tower of Hanoi Recursive Solution (Difficulty ⭐⭐⭐)

Problem: There are 3 pegs (A, B, C) and n disks. Initially, all disks are on peg A (smaller ones on top, larger ones on bottom). Move all disks to peg C, moving only one disk at a time, and never placing a larger disk on top of a smaller one. Output the steps.

Recursive approach:

  1. Move n-1 disks from A to B (using C)
  2. Move the nth disk from A to C
  3. Move n-1 disks from B to C (using A)
TEXT 📖 Display only
#include <iostream>

void hanoi(int n, char from, char to, char aux) {
 if (n == 1) { // Base case:Only one disk
 std::cout << "Move disk 1 from " << from << " to " << to << std::endl;
 return;
 }
 // Recursive case
 hanoi(n - 1, from, aux, to); // Move n-1 disks from source to auxiliary
 std::cout << "Move disk " << n << " from " << from << " to " << to << std::endl;
 hanoi(n - 1, aux, to, from); // Move n-1 disks from auxiliary to target
}

int main() {
 int n;
 std::cout << "Please enter number of disks: ";
 std::cin >> n;
 
 std::cout << "========== Tower of Hanoi Steps ==========\n";
 hanoi(n, 'A', 'C', 'B');
 
 return 0;
}

Output:

TEXT 📖 Display only
Move disk 1 from  to 
Move disk  from  to 
Please enter number of disks: 
========== Tower of Hanoi Steps ==========

Running result (n=3):

TEXT 📖 Display only
========== Tower of Hanoi Steps ==========
Move disk 1 from A to C
Move disk 2 from A to B
Move disk 1 from C to B
Move disk 3 from A to C
Move disk 1 from B to A
Move disk 2 from B to C
Move disk 1 from A to C

💡 Tip: The recursive solution for the Tower of Hanoi is very elegant, but if you try to write it with loops, you'll find it very difficult. That's the power of recursion.



7. Optimizing Recursion: Memoization

(1) 7.1 The Problem: Naive Recursion is Inefficient

The earlier Fibonacci recursive function recalculates many values:

TEXT 📖 Display only
fibonacci(5)
= fibonacci(4) + fibonacci(3)
= (fibonacci(3) + fibonacci(2)) + (fibonacci(2) + fibonacci(1))
= ...

fibonacci(2) is calculated 5 times! When n is large, efficiency is extremely low.

(2) 7.2 Solution: Memoization

Store previously calculated results and look them up directly next time.

CPP
#include <iostream>
#include <vector>

std::vector<long long> memo; // Memoization array

long long fibonacci(int n) {
 if (n == 0) return 0;
 if (n == 1) return 1;
 
 if (memo[n] != -1) { // If already calculated, return directly
 return memo[n];
 }
 
 memo[n] = fibonacci(n - 1) + fibonacci(n - 2); // Calculate and store
 return memo[n];
}

int main() {
 int n;
 std::cout << "Please enter a non-negative integer: ";
 std::cin >> n;
 
 memo.resize(n + 1, -1); // Initialize memoization array
 
 std::cout << "F(" << n << ") = " << fibonacci(n) << std::endl;
 
 return 0;
}

💡 Tip: C++11 introduced std::unordered_map, which can make memoization even more convenient.


❓ FAQ

Q Can recursion and loops be converted to each other?
A Yes! Any recursion can be rewritten as a loop (using a stack to simulate the call stack), and any loop can be rewritten as recursion.
Q Why is recursion inefficient?
A Because every function call has overhead: > 1. Parameters must be pushed onto the stack > 2. The return address must be pushed onto the stack > 3. Local variables must be allocated space
Q Can all problems be solved with recursion?
A Theoretically yes (since recursion and loops are equivalent), but some problems are actually more complex with recursion.

📖 Summary


📝 Exercises

  1. Basic (Difficulty ⭐): Write a recursive function int sumDigits(int n) that calculates the sum of the digits of an integer.
TEXT 📖 Display only
Input: 123
Output: 1 + 2 + 3 = 6

(Hint: recursive case sumDigits(n) = n % 10 + sumDigits(n / 10), base case n == 0)

  1. Intermediate (Difficulty ⭐⭐): Write a recursive function int power(int base, int exp) that calculates base raised to the power of exp.
TEXT 📖 Display only
Input: power(2, 5)
Output: 32

(Hint: recursive case power(b, e) = b * power(b, e-1), base case returns 1 when e == 0)

  1. Challenge (Difficulty ⭐⭐⭐): Use recursion to solve the "climbing stairs" problem:
  2. Suppose you need to climb n stairs, and you can climb 1 or 2 stairs at a time
  3. How many different ways are there to climb?
  4. (Hint: This is another version of the Fibonacci sequence — f(n) = f(n-1) + f(n-2))
  5. Optimize your recursive function with memoization

12. 🚀 Next Step

Now that you've learned recursion, let's move on to Function Overloading and Default Parameters (Lesson 13) — techniques to make functions more flexible and easier to use!

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏