Module 13 - Recursion and Recursive Functions Header

Module 13 - Recursion and Recursive Functions

Introducing Recursion

What is Recursion?

Recursion is a programming technique in which a function calls itself to solve a problem. In other words, a function that calls itself is known as a recursive function, and the process of a function calling itself is called recursion. Recursion is a powerful concept used in various algorithms and problem-solving scenarios.

Basic Example of Recursive Function: Factorial:

Let's start with a simple example of a recursive function to calculate the factorial of a positive integer.

def factorial(n):
if n == 0 or n == 1:
return 1
else:
return n * factorial(n - 1)

Explanation:

The factorial() function takes an integer n as input.
If n is 0 or 1, the function returns 1 as the factorial of 0 and 1 is 1.
Otherwise, the function returns the product of n and the result of calling factorial(n - 1), which calculates the factorial of the previous number.

Using the Recursive Factorial function:

print(factorial(5))  # Output: 120
print(factorial(0)) # Output: 1
print(factorial(1)) # Output: 1


Another Example of Recursion

Advanced Example of Recursive Function: Fibonacci Sequence:

The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones. Let's create a recursive function to calculate the nth number in the Fibonacci sequence.

def fibonacci(n):
if n <= 0:
return "Invalid input. Please provide a positive integer."
elif n == 1:
return 0
elif n == 2:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)

Explanation:

  1. The fibonacci() function takes a positive integer n as input.
  2. If n is less than or equal to 0, it returns an error message.
  3. If n is 1, the function returns 0, as it is the first number in the Fibonacci sequence.
  4. If n is 2, the function returns 1, as it is the second number in the Fibonacci sequence.
  5. Otherwise, the function returns the sum of the two preceding Fibonacci numbers calculated by recursively calling fibonacci(n - 1) and fibonacci(n - 2).

Example use of Recursive Fibonacci Sequence function:

print(fibonacci(7))  # Output: 8 (0, 1, 1, 2, 3, 5, 8)
print(fibonacci(10)) # Output: 34 (0, 1, 1, 2, 3, 5, 8,


Using Recursion

Use Cases for Recursion:

Recursion is suitable for solving problems where a task can be divided into smaller subproblems, and each subproblem is similar to the original problem but smaller in size. Some use cases include:

  • Calculating mathematical series (e.g., factorial, Fibonacci).
  • Traversing and searching trees and graphs.
  • Solving problems related to dynamic programming.
  • Backtracking algorithms (e.g., N-Queens problem, Sudoku).

Considerations and Limitations:

Recursive functions can lead to excessive function calls, potentially causing a stack overflow if the recursion depth is too high. It is essential to have a base case that terminates the recursion.\

  • Recursive functions might be less efficient than iterative solutions for some problems due to the overhead of function calls.
  • Properly handling base cases is crucial to ensure the termination of recursion and prevent infinite loops.
  • Recursion can be challenging to understand and debug, so clear documentation and well-defined base cases are essential.
  • Some problems may be better solved using iteration rather than recursion, as it can be more efficient and straightforward to implement.

When to Use Recursion and When Not To:

Recursion is an elegant approach for problems that have a natural recursive structure. It can lead to concise and readable code when the problem is well-suited for recursion. However, there are cases where recursion might not be the best choice:

  • Problems that have a straightforward iterative solution (e.g., simple loops).
  • Problems that require high performance and memory efficiency, as recursion can incur extra overhead.
  • Problems that have deep recursion depth, as it might lead to stack overflow.
  • Problems where the recursive solution results in redundant computations and inefficiency.

In conclusion, recursion is a powerful concept in programming that allows solving complex problems by breaking them down into smaller subproblems. It is well-suited for problems with recursive structures, but it should be used judiciously, considering the problem's complexity, efficiency, and stack depth to avoid potential issues.



Nested Lists and Recursion

A very common use of recursion is the exploration of nested lists or linked items to explore them, count them, or catalog them. Below, I've provided an example of this. I've included comments in the code to explain each line, and below that I've provided a more readable explanation of the list structure and the traversal process.The list will be at least three levels deep, and each level will have strings starting with the letters 'A', 'B', 'C', etc.

Explanation of the Nested List:

We'll create a nested list with the following structure:

  • At the top level, there will be strings starting with 'A'.
  • At the second level, there will be strings starting with 'B'.
  • At the third level (deepest level), there will be strings starting with 'C'.

The list structure will look like this:

['A1', 'A2', ['B1', 'B2', ['C1', 'C2'], 'B3'], 'A3']

Here is a diagram that might make the structure a bit more clear:

A figure showing the relationships between the parts of the list above

Explanation of Recursive Traversal:

The recursive function will start at the top level of the list and check each element:

  • If the element is a string, it will be counted as a leaf node.
  • If the element is a sublist (nested list), the function will call itself recursively on that sublist to explore the deeper levels.
  • The process continues until all elements in the nested list are traversed, and the count of leaf nodes is returned.

Python Code with Comments:

def count_leaf_nodes(nested_list):
   # Initialize the count to 0
   count = 0
# Iterate through each element in the nested list for element in nested_list: # If the element is a string, it is a leaf node, so increment the count if isinstance(element, str): count += 1
# If the element is a sublist (nested list), call the function recursively elif isinstance(element, list): count += count_leaf_nodes(element) # Return the total count of leaf nodes return count
# Nested list with strings at three levels deep nested_list = ['A1', 'A2', ['B1', 'B2', ['C1', 'C2'], 'B3'], 'A3'] # Call the recursive function to count leaf nodes result = count_leaf_nodes(nested_list) # Print the result print("Number of leaf nodes:", result) # Output: Number of leaf nodes: 6

Explanation of the Code:

  1. def count_leaf_nodes(nested_list): - Defines the recursive function count_leaf_nodes, which takes a nested list as input.
  2. count = 0 - Initializes the variable count to 0. This variable will keep track of the number of leaf nodes.
  3. for element in nested_list: - Iterates through each element in the nested list.
  4. if isinstance(element, str): - Checks if the current element is a string (leaf node). If so, increments the count by 1.
  5. elif isinstance(element, list): - Checks if the current element is a sublist (nested list). If so, calls the count_leaf_nodes() function recursively on the sublist to explore deeper levels.
  6. return count - After all elements in the nested list are traversed, the function returns the total count of leaf nodes.
  7. nested_list = ['A1', 'A2', ['B1', 'B2', ['C1', 'C2'], 'B3'], 'A3'] - Defines the nested list as described earlier.
  8. result = count_leaf_nodes(nested_list) - Calls the count_leaf_nodes() function with the nested list and stores the result in the variable result.
  9. print("Number of leaf nodes:", result) - Prints the total count of leaf nodes. In this case, the output is Number of leaf nodes: 6.

Note: The recursive function traverses the nested list by exploring each level and counting the leaf nodes along the way. It continues to call itself recursively on sublists until all elements are checked, and the final count is returned.

Videos for Module 13 - Recursion and Recursive Functions

Introduction to Recursion (3:03)

The Dragon Fractal (2:14)

The Tree Fractal (4:32)

The Snowflake Fractal (2:50)

Recursive Countdown (2:18)

List Traversal Logic (4:53)

List Traversal Code (7:53)

Key Terms for Module 13 - Recursion and Recursive Functions

No terms have been published for this module.

Quiz Yourself - Module 13 - Recursion and Recursive Functions

Test your knowledge of this module by choosing options below. You can keep trying until you get the right answer.

Skip to the Next Question