ScholarQuill logoScholarQuillUniversity Notes
  • Notes
  • Past Papers
  • Blogs
  • Todo
Login
ScholarQuill logoScholarQuillUniversity Notes
Login
NotesPast PapersBlogsTodo
More
SubjectsDiscussionCGPA CalculatorGPA CalculatorStudent PortalCourse Outline
About
About usPrivacy PolicyReportContact
Notes
Past Papers
Blogs
Todo
Analytics
    Current Subject
    🧩
    Discrete Structures
    GE-167
    Progress0 / 67 topics
    Topics
    1. Mathematical Reasoning: Propositional and Predicate Logic2. Propositional Logic: Logical Operators3. Translations Between Symbolic Expressions and Formal English Expression4. Logical Equivalences5. Predicate Logic: Quantifiers6. Nested Quantification7. Equivalences in Predicate Logic8. Translations Between Symbolic Forms and Formal English9. Rules of Inference: Proof Methods and Strategies10. Direct Proof11. Proof by Contraposition12. Proof by Induction13. Proof by Implication14. Existence Proof15. Uniqueness Proofs16. Trivial Proofs17. Vacuous Proofs18. Sets: Notations and Set Operations19. Venn Diagrams20. Countable and Uncountable Sets21. Relations: Equivalence Relations and Partitions22. Partial Orderings23. Recurrence Relations24. Functions: Injective, Surjective, Bijective25. Special Types of Functions26. Function Composition27. Inverse Functions28. Recursive Functions29. Compositions30. Number Theory: Sequences and Series31. Counting: Inclusion and Exclusion Principle32. Pigeonhole Principle33. Permutations and Combinations34. Integers and Divisibility: Division Theorem35. Modular Arithmetic36. LCM and GCD37. Euclidean and Extended Euclidean Method38. Finding Solutions to Congruence39. Primes: Fundamental Theorem of Arithmetic40. Characterizations of Primes41. Mersenne Primes42. Induction: Weak Induction43. Strong Induction44. Recursion and Recurrences: Formulation of Recurrences45. Closed Formulas46. Counting: Product Rule and Sum Rule47. Principle of Inclusion-Exclusion48. Binomial Coefficients49. Pascal's Identity and Pascal’s Triangle50. Binomial Theorem51. Relations: Reflexive, Symmetric, Transitive, and Antisymmetric52. Equivalence Relations and Equivalence Classes53. Partial Orders54. Graph Theory: Terminologies55. Elements of Graph Theory56. Planar Graphs57. Graph Coloring58. Euler Graph59. Hamiltonian Path60. Rooted Trees61. Graph Traversals62. Handshaking Lemma and Corollary63. Special Families of Graphs64. Graph Isomorphism65. Planarity in Graphs66. Eulerian and Hamiltonian Graphs67. Trees in Graph Theory
    GE-167›Recursive Functions
    Discrete StructuresTopic 28 of 67

    Recursive Functions

    9 minread
    1,474words
    Intermediatelevel

    Recursive Functions

    A recursive function is a function that calls itself as part of its execution. In mathematical terms and computer science, recursion is a method of solving problems where the solution to a problem depends on solutions to smaller instances of the same problem.

    Recursive functions are a fundamental concept in both mathematics and computer science. They allow complex problems to be broken down into simpler, manageable sub-problems that follow the same structure.


    1. Formal Definition of Recursive Functions

    In general, a recursive function f(n)f(n)f(n) is defined in terms of itself, and consists of two key components:

    1. Base Case(s): One or more simple conditions that do not require further recursion. These provide the stopping condition for the recursion.
    2. Recursive Case: An expression where the function calls itself with modified arguments, typically smaller or simpler values.

    The function continues to call itself until it reaches the base case, at which point the recursion stops and the function begins returning results back up the call stack.

    Mathematical Example

    Consider the factorial function, n!n!n!, which is commonly defined recursively:

    n!={1,if n=0n×(n−1)!,if n>0n! = \begin{cases} 1, & \text{if } n = 0 \\ n \times (n - 1)!, & \text{if } n > 0 \end{cases}n!={1,n×(n−1)!,​if n=0if n>0​

    Here:

    • Base case: 0!=10! = 10!=1.
    • Recursive case: n!=n×(n−1)!n! = n \times (n-1)!n!=n×(n−1)! for n>0n > 0n>0.

    The factorial function repeatedly reduces the problem of calculating n!n!n! into smaller sub-problems until it reaches the base case.


    2. Recursive Functions in Computer Science

    In computer science, recursion is a technique used in algorithms to solve problems. A recursive function solves a problem by solving smaller instances of the same problem. Each recursive call adds a new layer to the call stack, which must eventually return to the base case to terminate the recursion.

    Structure of a Recursive Function

    A recursive function typically has the following structure:

    def function_name(parameters):
        if base_case_condition:       # Base case
            return base_case_value
        else:
            return recursive_case_value
    
    • Base case: The simplest instance of the problem that does not involve recursion (terminates the recursion).
    • Recursive case: The part where the function calls itself with modified parameters, usually smaller in size or simpler.

    Example: Factorial Function in Python

    Here’s an implementation of the factorial function in Python:

    def factorial(n):
        if n == 0:  # Base case
            return 1
        else:
            return n * factorial(n - 1)  # Recursive case
    

    Explanation:

    • The base case is when n=0n = 0n=0, returning 111.
    • The recursive case reduces the problem to n×(n−1)!n \times (n-1)!n×(n−1)!, calling the function with n−1n-1n−1.

    3. Examples of Recursive Functions

    Let’s explore more examples of recursive functions to better understand the concept.

    Example 1: Fibonacci Sequence

    The Fibonacci sequence is defined recursively as:

    F(0)=0,F(1)=1,F(n)=F(n−1)+F(n−2) for n≥2.F(0) = 0, \quad F(1) = 1, \quad F(n) = F(n-1) + F(n-2) \text{ for } n \geq 2.F(0)=0,F(1)=1,F(n)=F(n−1)+F(n−2) for n≥2.

    This can be implemented as a recursive function:

    def fibonacci(n):
        if n == 0:  # Base case 1
            return 0
        elif n == 1:  # Base case 2
            return 1
        else:
            return fibonacci(n - 1) + fibonacci(n - 2)  # Recursive case
    

    Explanation:

    • The base cases are F(0)=0F(0) = 0F(0)=0 and F(1)=1F(1) = 1F(1)=1.
    • The recursive case calculates the next Fibonacci number by summing the two previous numbers in the sequence.

    Example 2: Sum of Integers

    The sum of the first nnn integers can be defined recursively as:

    S(n)=0if n=0,S(n) = 0 \quad \text{if } n = 0,S(n)=0if n=0, S(n)=n+S(n−1)if n>0.S(n) = n + S(n-1) \quad \text{if } n > 0.S(n)=n+S(n−1)if n>0.

    This can be implemented as:

    def sum_integers(n):
        if n == 0:  # Base case
            return 0
        else:
            return n + sum_integers(n - 1)  # Recursive case
    

    Explanation:

    • The base case is when n=0n = 0n=0, returning 0.
    • The recursive case adds nnn to the sum of integers from 000 to n−1n-1n−1.

    4. Tail Recursion and Head Recursion

    There are two main types of recursion based on where the recursive call is placed:

    a. Tail Recursion

    A recursive function is tail recursive if the recursive call is the last operation in the function. In tail recursion, there is no need to keep the current function’s state in memory once the recursive call is made. This can be more efficient in some programming languages because it allows for tail call optimization (where the system reuses the current function’s stack frame).

    Example: Tail-recursive factorial function:

    def factorial_tail_recursive(n, accumulator=1):
        if n == 0:
            return accumulator
        else:
            return factorial_tail_recursive(n - 1, n * accumulator)
    

    Here, the accumulator parameter accumulates the result as we recurse, so once we reach the base case, we return the result directly.

    b. Head Recursion

    In head recursion, the recursive call occurs before any computation is done in the function. This typically requires maintaining the function’s stack until the recursion reaches the base case.

    Example: Head-recursive factorial function (similar to the earlier example):

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

    This is head recursion because the recursive call happens first before multiplying by nnn.


    5. Advantages and Disadvantages of Recursion

    Advantages:

    1. Simplicity: Recursive solutions are often simpler and easier to understand, especially for problems that have a recursive structure (e.g., factorial, Fibonacci, tree traversal).
    2. Natural Fit for Certain Problems: Problems like tree traversal, dynamic programming, and divide-and-conquer algorithms are naturally expressed with recursion.
    3. Code Clarity: Recursion can result in cleaner, shorter code compared to iterative solutions.

    Disadvantages:

    1. Performance: Recursive functions can be inefficient due to repeated function calls and the overhead of maintaining the call stack. This can result in stack overflow if the recursion goes too deep.
    2. Memory Usage: Recursive calls can consume a lot of memory because each recursive call adds a new frame to the call stack.
    3. Difficulty in Debugging: It can be harder to debug recursive functions due to the complexity of tracing the recursive calls.

    6. Recursion in Divide-and-Conquer Algorithms

    One common use of recursion is in divide-and-conquer algorithms, where the problem is divided into smaller subproblems, each solved recursively. Some well-known algorithms that use recursion include:

    • Merge Sort: Recursively divides an array into halves, sorts each half, and merges them back together.
    • Quick Sort: Recursively partitions the array and sorts the sub-arrays.
    • Binary Search: Recursively divides the search space to find the target value.

    Conclusion

    Recursive functions are a powerful tool in mathematics and computer science for solving problems by breaking them down into smaller subproblems. They are defined by a base case (the simplest condition that does not require further recursion) and a recursive case (which calls the function with modified parameters). While recursion can simplify problem-solving, it also has potential drawbacks, such as inefficiency and memory usage. Understanding when and how to use recursion effectively is key to leveraging its advantages in solving problems.

    Previous topic 27
    Inverse Functions
    Next topic 29
    Compositions

    Past Papers

    Open this section to load past papers

    Click on Show Past Papers to see past papers.
    On This Page
      Reading Stats
      Est. reading time9 min
      Word count1,474
      Code examples0
      DifficultyIntermediate