Skip to content

Recursion

Recursion is a programming technique where a function calls itself directly or indirectly in order to solve a problem. A recursive function typically solves a problem by breaking it down into smaller and simpler sub-problems, and then combining the results of these sub-problems.

Key Concepts of Recursion

  1. Base Case: The condition under which the recursion ends. Without a base case, the recursion would continue indefinitely, leading to a stack overflow.
  2. Recursive Case: The part of the function where the function calls itself with a modified argument, moving towards the base case.

Example: Factorial Calculation

The factorial of a non-negative integer nnn (denoted as n!n!n!) is the product of all positive integers less than or equal to nnn. By definition:

  • 0!=10! = 10!=1
  • n!=n×(n−1)!n! = n \times (n-1)!n!=n×(n−1)! for n>0n > 0n>0

Recursive Implementation of Factorial

Here’s how you can implement the factorial function recursively in C++:

#include <iostream>

using namespace std;

int factorial(int n) {

    // Base case: if n is 0, return 1

    if (n == 0) {

        return 1;

    }

    // Recursive case: n * factorial(n-1)

    else {

        return n * factorial(n – 1);

    }

}

int main() {

    int number;

    cout << “Enter a positive integer: “;

    cin >> number;

    cout << “Factorial of ” << number << ” is ” << factorial(number) << endl;

    return 0;

}

Explanation

  • Base Case: The function checks if n is 0. If it is, the function returns 1, since 0!=10! = 10!=1.
  • Recursive Case: If n is not 0, the function returns n×factorial(n−1)n \times \text{factorial}(n-1)n×factorial(n−1). This breaks the problem into a smaller instance of itself.

Execution Flow for factorial(4)

  1. factorial(4) calls factorial(3)
  2. factorial(3) calls factorial(2)
  3. factorial(2) calls factorial(1)
  4. factorial(1) calls factorial(0)
  5. factorial(0) returns 1 (base case reached)
  6. factorial(1) returns 1×1=11 \times 1 = 11×1=1
  7. factorial(2) returns 2×1=22 \times 1 = 22×1=2
  8. factorial(3) returns 3×2=63 \times 2 = 63×2=6
  9. factorial(4) returns 4×6=244 \times 6 = 244×6=24

Thus, factorial(4) evaluates to 24.

Example: Fibonacci Sequence

The Fibonacci sequence is another classic example of recursion. The sequence is defined as follows:

  • F(0)=0F(0) = 0F(0)=0
  • F(1)=1F(1) = 1F(1)=1
  • F(n)=F(n−1)+F(n−2)F(n) = F(n-1) + F(n-2)F(n)=F(n−1)+F(n−2) for n>1n > 1n>1

Recursive Implementation of Fibonacci

#include <iostream>

using namespace std;

int fibonacci(int n) {

    // Base cases

    if (n == 0) {

        return 0;

    } else if (n == 1) {

        return 1;

    }

    // Recursive case

    else {

        return fibonacci(n – 1) + fibonacci(n – 2);

    }

}

int main() {

    int number;

    cout << “Enter a positive integer: “;

    cin >> number;

    cout << “Fibonacci number at position ” << number << ” is ” << fibonacci(number) << endl;

    return 0;

}

Explanation

  • Base Cases: The function returns 0 if n is 0 and returns 1 if n is 1.
  • Recursive Case: If n is greater than 1, the function returns the sum of fibonacci(n-1) and fibonacci(n-2).

Execution Flow for fibonacci(5)

  1. fibonacci(5) calls fibonacci(4) and fibonacci(3)
  2. fibonacci(4) calls fibonacci(3) and fibonacci(2)
  3. fibonacci(3) calls fibonacci(2) and fibonacci(1)
  4. fibonacci(2) calls fibonacci(1) and fibonacci(0)
  5. Base cases are reached:
    • fibonacci(1) returns 1
    • fibonacci(0) returns 0
  6. fibonacci(2) returns 1+0=11 + 0 = 11+0=1
  7. Continue computing upwards:
    • fibonacci(3) returns 1+1=21 + 1 = 21+1=2
    • fibonacci(4) returns 2+1=32 + 1 = 32+1=3
    • fibonacci(5) returns 3+2=53 + 2 = 53+2=5

Thus, fibonacci(5) evaluates to 5.

Advantages of Recursion

  1. Simpler Code: For problems that can be broken down into similar sub-problems, recursive solutions can be more straightforward and easier to understand.
  2. Modularity: Recursion allows for modular code, breaking down complex problems into simpler, self-contained units.

Disadvantages of Recursion

  1. Performance: Recursive solutions can be less efficient due to repeated calculations and function call overhead, leading to higher time and space complexity.
  2. Stack Overflow: Deep recursion can lead to stack overflow errors if the base case is not reached within a reasonable number of calls.

Conclusion

Recursion is a powerful technique that can simplify the implementation of complex problems. However, it should be used judiciously, keeping in mind the potential drawbacks such as performance issues and stack overflow risks. Understanding when and how to use recursion effectively is an essential skill for any programmer.