recursion


Concept: recursion

Recursion is a programming technique where a function calls itself directly or indirectly in order to solve a problem. The idea behind recursion is to break down a complex problem into smaller, more manageable subproblems, each of which is a simpler instance of the original problem. Recursion is particularly useful for tasks that can be defined in terms of similar subtasks, such as tree traversal, factorial computation, and solving puzzles like the Tower of Hanoi.

Key Characteristics of Recursion

Example 1: Factorial Calculation Using Recursion

One of the classic examples of recursion is the calculation of the factorial of a number.

#include <iostream>

// Function to calculate factorial of n using recursion
int factorial(int n) {
    if (n == 0 || n == 1) {  // Base case
        return 1;
    } else {  // Recursive case
        return n * factorial(n - 1);
    }
}

int main() {
    int number = 5;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;
    return 0;
}

Explanation:

Example 2: Fibonacci Sequence Using Recursion

The Fibonacci sequence is another classic example where recursion can be used. The sequence is defined as:

#include <iostream>

// Function to calculate factorial of n using recursion
int factorial(int n) {
    if (n == 0 || n == 1) {  // Base case
        return 1;
    } else {  // Recursive case
        return n * factorial(n - 1);
    }
}

int main() {
    int number = 5;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;
    return 0;
}

Explanation:

Example 3: Recursive Tree Traversal

Recursion is particularly well-suited for tree structures, where each node might have its own subtrees. Here is an example of a simple binary tree traversal.

#include <iostream>

struct Node {
    int data;
    Node* left;
    Node* right;
    Node(int val) : data(val), left(nullptr), right(nullptr) {}
};

// Function to perform an in-order traversal of the binary tree
void inOrderTraversal(Node* root) {
    if (root == nullptr) {
        return;  // Base case: if the node is null, return
    }

    inOrderTraversal(root->left);  // Traverse the left subtree
    std::cout << root->data << " ";  // Visit the root
    inOrderTraversal(root->right);  // Traverse the right subtree
}

int main() {
    // Create a simple binary tree
    Node* root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);

    std::cout << "In-order traversal: ";
    inOrderTraversal(root);
    std::cout << std::endl;

    // Free the allocated memory (not shown for simplicity)
    return 0;
}

Explanation:

Example 4: Tower of Hanoi Problem

The Tower of Hanoi is a classic problem that is often solved using recursion. The goal is to move a set of disks from one rod to another, following specific rules.

#include <iostream>

// Function to solve the Tower of Hanoi problem
void towerOfHanoi(int n, char source, char destination, char auxiliary) {
    if (n == 1) {
        std::cout << "Move disk 1 from " << source << " to " << destination << std::endl;
        return;  // Base case: Only one disk to move
    }

    towerOfHanoi(n - 1, source, auxiliary, destination);  // Move n-1 disks from source to auxiliary
    std::cout << "Move disk " << n << " from " << source << " to " << destination << std::endl;
    towerOfHanoi(n - 1, auxiliary, destination, source);  // Move n-1 disks from auxiliary to destination
}

int main() {
    int n = 3;  // Number of disks
    towerOfHanoi(n, 'A', 'C', 'B');  // A is source, C is destination, B is auxiliary
    return 0;
}

Explanation:

Recursion vs. Iteration

While recursion is a powerful tool, it's not always the best choice. In some cases, iterative solutions may be more efficient or easier to understand. For instance, deep recursion can lead to stack overflow if the recursion depth is too great, and some problems that are naturally recursive may have more efficient iterative solutions.

Summary

Understanding recursion is fundamental to mastering algorithms and problem-solving in programming. It's a powerful tool that, when used appropriately, can simplify the implementation of complex problems.

Previous Page | Course Schedule | Course Content