Recursion is a programming technique in which a function calls itself to solve a problem. A recursive function usually has two important parts: a base case, which stops the recursion, and a recursive case, which calls the function again with a smaller or simpler problem.
Recursion occurs when a function calls itself directly or indirectly.
void countDown(int number) {
if (number == 0) {
return;
}
std::cout << number << std::endl;
countDown(number - 1);
}
Here, countDown() calls itself with a smaller value.
A recursive function generally performs these steps:
The function calls are stored in memory until the recursive process finishes.
#include <iostream>
void message(int number) {
if (number == 0) {
return;
}
std::cout << "Hello" << std::endl;
message(number - 1);
}
int main() {
message(3);
return 0;
}
Output:
Hello
Hello
Hello
The base case is the condition that stops a recursive function.
void count(int number) {
if (number == 0) {
return;
}
std::cout << number;
count(number - 1);
}
In this example, number == 0 is the base case.
The recursive case is the part where the function calls itself.
void count(int number) {
if (number == 0) {
return;
}
std::cout << number << std::endl;
count(number - 1);
}
The statement count(number - 1) is the recursive case.
void countDown(int number) {
if (number == 0) {
return;
}
std::cout << number << std::endl;
countDown(number - 1);
}
int main() {
countDown(5);
return 0;
}
Output:
5
4
3
2
1
void countUp(int number) {
if (number == 0) {
return;
}
countUp(number - 1);
std::cout << number << std::endl;
}
int main() {
countUp(5);
return 0;
}
Output:
1
2
3
4
5
The position of the recursive call affects the output order.
Factorial is a common example of recursion.
int factorial(int number) {
if (number == 0) {
return 1;
}
return number * factorial(number - 1);
}
int main() {
std::cout << factorial(5);
return 0;
}
Output:
120
The calculation is based on:
5 × 4 × 3 × 2 × 1 = 120.
For factorial(5), the function calls itself like this:
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)
When factorial(0) returns 1, the previous calls can
complete their calculations.
A recursive function can return a value just like a normal function.
int sum(int number) {
if (number == 0) {
return 0;
}
return number + sum(number - 1);
}
For example, sum(5) returns:
5 + 4 + 3 + 2 + 1 = 15
int sum(int number) {
if (number == 0) {
return 0;
}
return number + sum(number - 1);
}
int main() {
int result = sum(10);
std::cout << "Sum = "
<< result;
return 0;
}
Output:
Sum = 55
The Fibonacci sequence is another common example of recursion.
int fibonacci(int number) {
if (number <= 1) {
return number;
}
return fibonacci(number - 1)
+ fibonacci(number - 2);
}
int main() {
std::cout << fibonacci(6);
return 0;
}
For this example, the result is:
8
void printNumbers(int number) {
if (number > 10) {
return;
}
std::cout << number << " ";
printNumbers(number + 1);
}
int main() {
printNumbers(1);
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10
void reverseNumbers(int number) {
if (number == 0) {
return;
}
std::cout << number << " ";
reverseNumbers(number - 1);
}
int main() {
reverseNumbers(10);
return 0;
}
Output:
10 9 8 7 6 5 4 3 2 1
int power(int base, int exponent) {
if (exponent == 0) {
return 1;
}
return base * power(base, exponent - 1);
}
int main() {
std::cout << power(2, 4);
return 0;
}
Output:
16
The function calculates 2 × 2 × 2 × 2.
A recursive function can have multiple parameters.
int power(int base, int exponent) {
if (exponent == 0) {
return 1;
}
return base * power(base, exponent - 1);
}
Here, base stays the same while exponent
gets smaller with every recursive call.
The Greatest Common Divisor (GCD) can be calculated recursively.
int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
int main() {
std::cout << gcd(48, 18);
return 0;
}
Output:
6
Recursion can also be used to process characters of a string one by one.
#include <iostream>
#include <string>
void printString(std::string text, int index) {
if (index == text.length()) {
return;
}
std::cout << text[index] << std::endl;
printString(text, index + 1);
}
The index increases until it reaches the end of the string.
Each function call is stored on the program's call stack. When a recursive function calls itself, a new function call is added to the stack.
void test(int number) {
if (number == 0) {
return;
}
test(number - 1);
}
When the base case is reached, the calls return one by one.
A recursive function without a proper stopping condition can continue calling itself.
void test() {
test();
}
This function has no base case. It can continue making function calls until the available stack memory is exhausted.
When a function directly calls itself, it is called direct recursion.
void count(int number) {
if (number == 0) {
return;
}
count(number - 1);
}
The function count() directly calls itself.
Indirect recursion occurs when one function calls another function and that function eventually calls the first function again.
void second();
void first(int number) {
if (number == 0) {
return;
}
second();
}
void second() {
first(0);
}
Here, the functions are connected through each other.
| Recursion | Loop |
|---|---|
| Function calls itself. | Repeats using loop statements. |
| Uses the call stack. | Usually uses less call-stack overhead. |
| Can make some problems easier to express. | Often simpler for straightforward repetition. |
| Needs a base case. | Needs a loop condition. |
Recursion can be useful for problems that naturally contain smaller versions of the same problem.
int sumDigits(int number) {
if (number == 0) {
return 0;
}
return (number % 10)
+ sumDigits(number / 10);
}
int main() {
std::cout << sumDigits(1234);
return 0;
}
Output:
10
The digits are processed as 4 + 3 + 2 + 1.
#include <iostream>
int factorial(int number) {
if (number <= 1) {
return 1;
}
return number * factorial(number - 1);
}
int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;
std::cout << "Factorial = "
<< factorial(number);
return 0;
}
This program takes a number from the user and calculates its factorial using recursion.
#include <iostream>
int sum(int number) {
if (number == 0) {
return 0;
}
return number + sum(number - 1);
}
int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;
std::cout << "Sum = "
<< sum(number);
return 0;
}
| Concept | Meaning |
|---|---|
| Recursion | A function calling itself. |
| Base Case | The condition that stops recursion. |
| Recursive Case | The part that calls the function again. |
| Call Stack | Memory structure used to keep track of function calls. |
| Direct Recursion | A function directly calls itself. |
| Indirect Recursion | Functions call each other in a recursive cycle. |
| Common Uses | Factorial, trees, backtracking, divide-and-conquer, and similar problems. |
returnType functionName(parameters) {
if (baseCondition) {
return result;
}
return functionName(smallerProblem);
}
Question: What is the most important purpose of a base case in recursion?