More Recursion
reading: Dietel pp. xxx
Kinds of Recursion
- Direct Recursion: function contains an explicit call to itself (what we've seen so far)
- Indirect Recursion: function F calls function G, which in turn calls function F
- Tail Recursion: return value of function is return value of recursive call (no pending operations)
- Linear Recursion: no pending operation invokes another recursive call (Factorial, below)
- Tree Recursion: some pending operation invokes another recursive call (Fibonacci)
Converting Tail Recursion to Iteration
- Iteration usually more efficient
- Some algorithms more naturally expressed recursively
- Want to convert initial recursive algorithm to iterative algorithm
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?
- Same as when any other function call is made
- Call stack: memory to track data associated with function calls
- Calling function pushes any parameters onto stack
- Calling function pushes its return address on the stack
- Called function pushes any local variables on the stack
- Called function proceeds as usual
- When done, pops off local variables and returns to return address
- Calling function then pops off address, parameters
- Limited stack memory limits recursion (or any function call) depth