Recursive Functions in C++
COS2611 - Programming: Data Structures · Recursion
Recursive Functions in C++
Recursive functions are functions that call themselves in order to solve a problem. They are a key concept in programming, especially in data structures and algorithms. In C++, recursion can simplify code and make it easier to read, but it can also lead to complex problems if not handled correctly.
Understanding Recursive Functions
A recursive function typically has two main parts: the base case and the recursive case. The base case stops the recursion, while the recursive case continues the process.
Base Case
The base case is a condition that allows the function to stop calling itself. If there is no base case, the function will continue to call itself indefinitely, leading to a stack overflow error.
Recursive Case
The recursive case is where the function calls itself with modified arguments. This allows the function to break down the problem into smaller, more manageable pieces.
Remember: Always define a base case to avoid infinite recursion.
Example: Factorial Function
The factorial of a non-negative integer n, denoted as n!, is the product of all positive integers less than or equal to n. The factorial can be defined recursively as follows:
- Base case: 0! = 1
- Recursive case: n! = n × (n - 1)! for n > 0
Here is how you can implement the factorial function in C++:
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}In this example, if you call factorial(5), the function will evaluate as follows:
factorial(5) → 5 × factorial(4)
factorial(4) → 4 × factorial(3)
factorial(3) → 3 × factorial(2)
factorial(2) → 2 × factorial(1)
factorial(1) → 1 × factorial(0)
factorial(0) → 1
Then, the multiplication will be completed in reverse order:
factorial(1) → 1
factorial(2) → 2 × 1 = 2
factorial(3) → 3 × 2 = 6
factorial(4) → 4 × 6 = 24
factorial(5) → 5 × 24 = 120
Example: Fibonacci Sequence
The Fibonacci sequence is another classic example of recursion. The sequence is defined as follows:
- Base cases: F(0) = 0, F(1) = 1
- Recursive case: F(n) = F(n - 1) + F(n - 2) for n > 1
Here is how you can implement the Fibonacci function in C++:
int fibonacci(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}When you call fibonacci(5), the function evaluates as follows:
fibonacci(5) → fibonacci(4) + fibonacci(3)
fibonacci(4) → fibonacci(3) + fibonacci(2)
fibonacci(3) → fibonacci(2) + fibonacci(1)
fibonacci(2) → fibonacci(1) + fibonacci(0)
fibonacci(1) → 1
fibonacci(0) → 0
Continuing this process will yield the Fibonacci numbers:
fibonacci(2) → 1
fibonacci(3) → 2
fibonacci(4) → 3
fibonacci(5) → 5
Watch Out for Performance Issues
Watch out: The recursive Fibonacci function has exponential time complexity. This means that it can be very slow for larger values of n. Consider using an iterative approach or memoisation to improve performance.
Tail Recursion
Tail recursion is a special case of recursion where the recursive call is the last operation in the function. This allows some compilers to optimise the code and reduce the amount of stack space used. Not all recursive functions can be made tail recursive, but it can be beneficial when possible.
Example: Tail Recursive Factorial
Here is how you can implement a tail recursive version of the factorial function:
int tail_recursive_factorial(int n, int accumulator = 1) {
if (n == 0) {
return accumulator;
} else {
return tail_recursive_factorial(n - 1, n * accumulator);
}
}In this version, the accumulator variable carries the result of the factorial computation, and the recursive call is the last operation performed.
Self-Check Questions
- What is the difference between a base case and a recursive case in a recursive function?
- How does the factorial function work when called with the argument 4?
- What are the performance implications of using recursion for the Fibonacci sequence?
- What is tail recursion and how does it differ from regular recursion?
Summary:
- A recursive function calls itself to solve a problem.
- It consists of a base case and a recursive case.
- Examples include the factorial function and the Fibonacci sequence.
- Tail recursion can optimise memory usage in some cases.