Recursion

Reading: Chapter 10

Fabulously complex structure, simple procedures

Definition

Recursion?? What's that?

Recursion is the concept of well-defined self-reference.

Recursive definitions

A Sierpinski gasket is three half-sized Sierpinski gaskets arranged in a triangle.

Recurrences

Recursion turns up in mathematics all the time!

Recurrences are recursive mathematical formulas.

Example:

       { 1                   if n = 1 or n = 2
F(n) = {
       { F(n - 2) + F(n - 1) otherwise
This is the definition of the famed Fibonacci sequence
n1234567...
F(n)11235813...

But recursion is just as much a computer science concept!

Exponentiation

Problem EXPONENTIATION:
Input: a number x and a positive integer n.
Output: the value xn.

We can first write a recurrence.

         { 1              if n = 0
E(x,n) = {
         { x E(x, n - 1)  if n > 0

Now we write a program.

double exponentiate(double x, int n) {
    if(n == 0) {
        return 1.0;
    } else {
        return x * exponentiate(x, n - 1);
    }
}

int main() {
    double x;
    int n;
    cout << "Take what to the what? ";
    cin >> x >> n;
    cout << exponentation(x, n) << endl;
    return 0;
}

The call stack

To trace how the program works, we use a call stack.

exponentation(2, 5) returns 32
exponentation(2, 4) returns 16
exponentation(2, 3) returns  8
exponentation(2, 2) returns  4
exponentation(2, 1) returns  2
exponentation(2, 0) returns  1

Couldn't a recursive algorithm go on forever?

Every recursive algorithm must have a case in which it does not recurse - called the base case. (Just like induction!)

Faster exponentiation

But what about this instead?

If n is even, xn = (x2)n/2.


If n is odd, xn = x * (x2)(n-1)/2.


This can be a lot faster.

double exponentatiate(double x, int n) {
    if(n == 0) {
        return 1.0;
    } else if(n % 2 == 0) {
        return fastExp(x * x, n / 2);
    } else {
        return x * fastExp(x * x, (n - 1) / 2);
    }
}

The call stack for (x=2,n=5).

exponentation(  2, 5) returns 32
exponentation(  4, 2) returns 16
exponentation( 16, 1) returns 16
exponentation(256, 0) returns  1

Towers of Hanoi

   |       |       |
  $$$      |       |
 @@@@@     |       |
#######    |       |
---+-------+-------+---
   a       b       c

Goal: move towers from a to b.

Rules:

A recursive solution

  1. Move all but largest disk from a to c (recursively!).
  2. Move largest from a to b.
  3. Move all but largest to b (recursively).

Pseudocode:

Algorithm Hanoi(disk, src, dst, space)
if disk = 0 then
  Move disk from src to dst.
else
  Hanoi(disk - 1, src, spare, dst)
  Move disk from src to dst.
  Hanoi(disk - 1, spare, dst, src)
end of if
To start, we call Hanoi(2, a, b, c).

We can use a call stack to trace this, or we can use a call tree:

              2,a,b,c
     1,a,c,b           1,c,b,a
0,a,b,c  1,b,c,a  1,c,a,b  1,a,b,c

Analysis of Hanoi

How much longer 'til the world ends?

Define a recurrence:

       { 1                   if n = 1
H(n) = {
       { H(n-1) + 1 + H(n-1) if n > 1
Solve:
nH(n)
11
23
37
415
531
::
Prove:
H(n) = 2n - 1

A REAL puzzle:
What's the best algorithm for moving n disks using 4 pegs?