15B. Recursion

Recall that, whenever a function is called, it gets a new frame. So each call has its own variables. A consequence of that is that a function can call itself. It actually calls a copy of itself, with a new frame. A function that calls itself is said to be recursive, or to use recursion.


Example

Let's write a definition of function factorial(n) that returns n! = 1×2×…×n. The following two facts should be clear.

0! = 1  (by definition)
n! = n×(n−1)!  (if n > 0)

For example,

5! = 5×4×3×2×1
  = 5×(4×3×2×1)
  = 5×4!

Those facts suggest the following definition of factorial, which works correctly as long as n ≥ 0.

  int factorial(const int n)
  {
    if(n == 0)
    {
      return 1;
    }
    else
    {
      return n * factorial(n-1);
    }
  }

Planning for recursive functions

The preceding example illustrate a few features of recursion.

  1. Recursive functions are based on facts, and a plan for a recursive function definition concentrates on facts.

  2. The body of a recursive function definition is broken down into two or more cases.

  3. At least one of the cases must not use recursion. Such a case is called a base case.

  4. Recursion does not require as much planning ahead as loops do. You can work out and code each case separately.

What the preceding example does not show is the utility of recursion. Programmers have found that recursive function definitions tend to be highly reliable. If you are careful when establishing the basic facts, then your function definitions work the first time you try them more often than you think you have a right to.


Variables and recursion

Factorial has a const parameter, n, and no additional variables. That is typical of recursive functions. If you find yourself changing the value of a variable in a recursive function definition, be sure that you understand exactly why you are doing that. You are probably better off only using constants, or having no variables or constants other than the parameters.

At this stage in your studies, if you change a variable in a recursive function definition, it almost certainly means that you misunderstand recursion.


Recursion is a substitute for a loop

Do not try to use both recursion and a loop in the same function until you are an expert. Use one or the other. Every job that can be done with a loop can also be done with recursion and every job that can be done with recursion can be done with a loop. But one is often much easier than the other.

You will find that loops work well for some problems, but they are somewhat inflexible, and require you to do complicated workarounds for some problems. Recursion is more flexible and often gives you short and easy solutions to problems that are difficult to solve with a loop.


Exercises

  1. What is the value of g(4), given the definition of g below? (Hint. Work out g(1), then g(2), then g(3), then g(4), in that order. Keep your work organized.)

      int g(const int n)
      {
        if(n == 1) 
        {
          return 2;
        }
        else 
        {
          return g(n-1) + 3;
        }
      }
    
    Answer

  2. Write a C++ definition of function sum(a, b) that returns a + (a+1) + ... + b. For example, sum(2,5) = 2 + 3 + 4 + 5 = 14. More precisely, sum(a, b) returns the sum of all integers that are greater than or equal to a and less than or equal to b. For this question do not use any kind of loop. Use recursion instead. Answer