Skip to main content

Mutual Recursion

Definition​

Mutual recursion occurs when two or more functions recursively call each other. This means that the execution of one function depends on the execution of another, allowing for a collaborative approach to solving problems.

Why It Is Useful​

Mutual recursion is useful for problems where two or more related tasks need to be handled in tandem. It is particularly applicable in:

  • Algorithms that involve alternating behaviours, such as even and odd calculations.
  • Solving problems in graph theory, where different conditions can trigger different functions.

Time Complexity Analysis​

Best Case​

The best case occurs when the mutual recursion reaches the base case quickly, requiring minimal calls.

Example: For a simple alternating function that checks even and odd:

def is_even(n):
if n == 0:
return True
return is_odd(n - 1)

def is_odd(n):
if n == 0:
return False
return is_even(n - 1)

If n=0n = 0, the function returns immediately.

Time Complexity:
O(1)O(1)

Worst Case​

The worst case occurs when the mutual recursion continues to call each other before reaching a base case.

Example: Using the same alternating function: For n=5n = 5, the function makes multiple calls, alternating between is_even and is_odd.

Time Complexity:
O(n)O(n)

Example Using Mutual Recursion​

Problem: Check Even or Odd​

Dry Run​

For n=3n = 3, the recursive process would look like this:

  1. Start with is_even(3)
    • Calls is_odd(2)
    • Calls is_even(1)
    • Calls is_odd(0)
    • Returns False (base case)
    • Returns True (1 is odd)
    • Returns False (2 is even)
    • Returns True (3 is odd)

Final Result: is_even(3) returns False, indicating that 3 is odd.

Advantages of Mutual Recursion​

  1. Structured Code: Mutual recursion can provide a more organized structure for code by separating different behaviours into distinct functions.

  2. Clear Logic: It can make the logic of certain algorithms clearer, especially when two functions are clearly related to the problem at hand.

  3. Natural Problem Solving: Some problems naturally fit into a mutual recursion pattern, allowing for straightforward implementation.

Disadvantages of Mutual Recursion​

  1. Complexity: Understanding and debugging mutual recursion can be more complex than single recursion due to the interaction between functions.

  2. Performance Issues: Similar to tree recursion, mutual recursion can lead to inefficiencies if not optimized, particularly in terms of time complexity.

  3. Stack Overflow Risk: Deep mutual recursion can also lead to stack overflow errors, especially in languages without tail call optimization.

Code Implementation of Mutual Recursion​

C Implementation:​

#include <stdio.h>

int is_even(int n);
int is_odd(int n);

int is_even(int n) {
if (n == 0) {
return 1; // True (0 is even)
}
return is_odd(n - 1);
}

int is_odd(int n) {
if (n == 0) {
return 0; // False (0 is not odd)
}
return is_even(n - 1);
}

int main() {
int number = 3;
if (is_even(number)) {
printf("%d is even\n", number);
} else {
printf("%d is odd\n", number);
}
return 0;
}

Python Implementation:​

def is_even(n):
if n == 0:
return True # 0 is even
return is_odd(n - 1)

def is_odd(n):
if n == 0:
return False # 0 is not odd
return is_even(n - 1)

number = 3
if is_even(number):
print(f"{number} is even")
else:
print(f"{number} is odd")

Java Implementation :​

public class MutualRecursion {
public static boolean isEven(int n) {
if (n == 0) {
return true; // 0 is even
}
return isOdd(n - 1);
}

public static boolean isOdd(int n) {
if (n == 0) {
return false; // 0 is not odd
}
return isEven(n - 1);
}

public static void main(String[] args) {
int number = 3;
if (isEven(number)) {
System.out.println(number + " is even");
} else {
System.out.println(number + " is odd");
}
}
}