Dataslope logoDataslope

Recursion

Learn recursive thinking, the call stack, classic recursive functions, stack overflow, and recursion trade-offs in C++

Recursion is a technique where a function solves a problem by calling itself on a smaller version of the same problem. It is a natural fit for trees, divide-and-conquer algorithms, backtracking, and definitions that already refer to themselves.

Recursive thinking

Every correct recursive function needs two parts:

PartPurpose
Base caseStops on the smallest input
Recursive caseReduces the problem and calls the same function

This mirrors mathematical induction: prove the smallest case, then show that a correct answer for a smaller input leads to a correct answer for the next input.

Ask two questions

What is the smallest input I can answer immediately? How does every other input move closer to that input?

The call stack

Each call gets its own stack frame containing parameters, local variables, and a return address. Recursive calls add frames until a base case returns.

Factorial

n! means n * (n - 1) * ... * 1, and 0! is 1.

Code Block
C++ 20 (202002L)

Naive Fibonacci

The Fibonacci sequence is recursive by definition: fib(n) = fib(n - 1) + fib(n - 2). The direct version is short, but exponential because it repeats subproblems.

Code Block
C++ 20 (202002L)

Repeated calls motivate memoization, a dynamic programming idea we will revisit later.

Recursive array sum

A recursive array function often carries an index that moves toward the end.

Code Block
C++ 20 (202002L)

Power: naive and fast

Naive recursive power multiplies by a exactly n times, so it is O(n).

Code Block
C++ 20 (202002L)

Fast exponentiation squares a half-power and reduces the exponent by half, giving O(log n).

Code Block
C++ 20 (202002L)

Stack overflow and tail recursion

A stack overflow happens when recursive calls create more frames than the stack can hold. Causes include missing base cases, huge inputs, or recursion that shrinks too slowly. Avoid it by verifying the base case, switching to iteration for deep inputs, converting tail recursion to a loop, or increasing stack size only when you control the runtime.

Tail recursion means the recursive call is the final action. Clang may optimize some tail calls, but C++ does not guarantee this optimization.

Code Block
C++ 20 (202002L)

Recursion vs iteration

Recursion can make tree-shaped logic elegant and close to the math. Iteration usually uses less memory, avoids stack-depth limits, and can be faster. Choose clarity first, then adapt when constraints require it.

Practice: count digits recursively

Challenge
C++ 20 (202002L)
Count digits of a positive integer recursively

Implement int countDigits(int n). The input is positive. Do not print inside the function; the driver prints several calls.

Practice: reverse a string recursively

Challenge
C++ 20 (202002L)
Reverse a string recursively

Implement std::string reverseStr(const std::string& s) recursively. The driver prints the reverse of recursion.

Check your understanding

QuestionSelect one

Why is a base case necessary in recursion?

It makes the function run in O(1) time.

It stops recursive calls from continuing forever.

It stores all previous answers automatically.

It lets C++ allocate variables on the heap.

QuestionSelect one

What is the time complexity of naive recursive Fibonacci?

O(n)

O(n log n)

Exponential, often written as O(2^n)

O(log n)

QuestionSelect one

What does recursion use under the hood to remember unfinished calls?

A priority queue

A hash table

The call stack

A sorted vector

On this page