Review of Recursion
Objectives of this lecture
q Review how recursive functions works, their good and
bad points
q Study some examples of recursive functions.
Review
q We recall that a recursive function is one that call
itself, or start call chain that eventually calls itself.
q It is based of the divide and conquer problem-solving
approach.
q It is a very powerful tool for simplifying algorithms
q However, it can also be very expensive in terms of
memory requirement
q A recursive function generally consists of two parts:
The recursive part, in which the function calls itself, and the stopping part
(also called the base case) which stops the recursion.
Example 1:
q The most popular example of recursion in the
implementation of factorial function, which is defined mathematically as:
q The implementation is almost a direct representation
of this definition
/*
Factorial: compute n!
Pre: n is a nonnegative integer.
Post:
The function value is the factorial of n.
*/
int
factorial(int n)
{ if (n==0)
return 1;
else
return (n*factorial(n-1));
}
q Notice however, the memory required by this function
depends on the size of n. From one call
to the next, the system has to create an activation record in the system stack
(another application of stack) to hold the variables of the current call.
q Recursive calls (like other function calls) are
usually represented graphically using stack frames or recursive trees as shown by the following figures:
q Notice that the amount of memory required is
determined by the height of the recursive tree not by the number of recursive
calls.
Example 2: Towers of Hanoi problem:
q Another popular example that demonstrates the use of
recursion is the Towers of Hanoi problem.
q It involves moving a number of disk stacked in order
of size from one pole (pole 1) to another pole (pole 3) using a middle pole
(pole 2) as a resting place. However,
the movement must be done such that a bigger pole is never put on top of a
smaller disk.
Solution.
q We observe that there is no way to reach the bottom
disk until all the other disks are on the middle pole. Similarly, moving the next largest from pole
2 to 3, we need to first move all the other disks to pole 1. This process, thus continue until we are
left with the smallest disk, which is paced directly on pole 3.
q The algorithm above can be implemented as follows:
/*
Move: moves count disks from start to finish using temp
for
temporary storage. */
void
Move(int count, int start, int finish, int temp)
{
if (count > 0) {
Move(count-1, start, temp, finish);
printf("Move a disk from %d to
%d.\n", start, finish);
Move(count-1, temp, finish, start);
}
}
Analysis.
q The best way to analyze a recursive function is to
draw its recursive tree. This is shown
below for n=3.
q Notice that each recursive call reduces the number of
disks by 1. Thus, the
depth of the recursion is n.
q Notice also that except for the leaves, each recursive
call (vertex) results in two other recursive call.
q Thus, the number of non-recursive calls is given by
the series:
1+2+4+
… + 2n-1.
q This is clearly a geometric series with :
First
element, a = 1
Common
ratio, r=2
Number
of elements = n.
i.e. number of recursive calls = (arn-1)/(r-1)
=2n-1.
q Note: This is
an example of algorithm with exponential order, O(2n).
q A visual program that implements the towers of Hanoi
problem is on my Home page.
Exercise:
Answer exercises
E1 and E2 of page 100 of your book.