More about Recursion

    reading: Dietel sections 3.13-3.14

     Example: Fibonacci Numbers

int Fibonacci (int n)

{

    if( n < 0 )  // Fibonacci not defined on negative numbers

        return -1; 

     if( n == 0 || n == 1)  // Can use non-recursive part of definition

        return 1;

    return ( Fibonacci(n-1) + Fibonacci(n-2) ); // Well-defined since n >= 2

}

 

int Fibonacci (int n)

{

    int f0 = 1, f1 = 1; // Each Fibonacci based on previous two

    if( n == 0 || n == 1) // Don't need recursive definition

        return 1;

    if( n < 0)  // Not defined on negative numbers

        return -1;

    int new_fib, index = 2;  // F(index) is current computation  

    while( index <= n ) // Iteratively compute result, one step at a time

        {

            new_fib = f0 + f1;

            f0 = f1;

            f1 = new_fib;

            index++;

        }

    return new_fib;

}

Example: String Reversal

void StringReverse (string s)

{

    if( s.length() == 0 )  // No characters remain; done

        return;

    StringReverse( string( s.begin() + 1, s.end() ) ); // Reverse rest of
                                                                               //   string

    cout << s[0];  // Print out first character last

}        // Note array-style string access

 

void StringReverse (string s)

{

   int length = s.length(); // Number of characters to output

   for( int i = length-1; i > = 0; i--)  // Reverse order of output

           cout << s[i];

}

 

Recursion vs. Iteration

 

Approach to Writing Recursive Functions

Correctness of Recursive Algorithms

 

Kinds of Recursion

Converting Tail Recursion to Iteration

General Skeleton of Tail Recursion

type F ( type x )

{

    if ( P(x) )           // Test for base case; form return value

        return G(x);

    return F( H(x) );  // Make recursive call; may need to modify input.

}

Iterative Version

type F( type x)

                    {

                        type temp_x;

                        while ( ! P(x) )   // As long as we haven't hit the base case

                        {

                            temp_x = x; // Compute new value of parameter

                            x = H( temp_x );

                        }

                        return G(x);     // Perform any necessary modifications for base case

                    }

Example: Factorial

   Tail-Recursive Version -- Initial call is Factorial(n,1);

    int Factorial( int n, int result)

    {

        if ( n == 1 ) // Test for base case; no further multiplication necessary

            return result;

        return Factorial( n-1, n * result );  // Multiply n into result so far;

                                                           //  recursive call computes rest.

    }

    Iterative Version

int Factorial( int n )

{

    int temp_n, temp_result, result = 1; 

    while( n != 1 )        // As long as this isn't the base case

    {

        temp_n = n;        // Save old values

        temp_result = result;

        n = temp_n - 1; // Compute new values

        result = temp_result * temp_n;

    }

    return result;           // No modifications necessary for base case

}  

What happens when recursive calls are made?