UMBC CMSC202, Computer Science II, Spring 1998,
Sections 0101, 0102, 0103, 0104 and Honors
Thursday February 5, 1998
- Programming Abstractions in C: 5.1-5.2
Handouts (available on-line): none
- The Fibonacci numbers are defined recursively, so we can
easily write a program with a recursive
function that computes the nth Fibonacci number. ( Sample run.)
- Note the use of argc and argv in the
parameter list of the main function. These parameters
allow us to access the command line arguments that were typed in at
the UNIX prompt.
- This program is really slow. It took 3 minutes and 22 seconds to
compute the 42nd Fibonacci number. The reason is that the fib()
function is called over and over again for the same values. For
example, to compute fib(n), the value of fib(1)
is computed fib(n-1) times. Since the Fibonacci numbers
grow very quickly, this makes our program very slow.
- One way to fix the problem of repeatedly computing the same
values of fib(i) is to use a memoization table. (Note:
the word is not "memorization".) In this approach, after we compute
the value of fib(i) for the first time, we record it in the
memoization table. If the function fib() is called with
parameter i again, the value from the table is retrieved
and returned. This approach reduces the number of recursive calls
dramatically and gives us a much faster program. The sample run
shows that the new running time to compute fib(42) is less
than 0.1 seconds.
- The greatest common divisor (gcd) of two numbers m and n is
the largest integer that divides both m and n. We show how recursion
is used to find a fast algorithm to compute gcd.
- First, we implement a naive algorithm to compute the gcd of two
numbers. This program simply tries every
number between 2 and the smaller of m and n. The largest divisor
is returned. The sample run shows that
this program is quite slow. It took 22 seconds in one case to
compute the gcd of two large-ish numbers.
- Euclid, an ancient Greek mathematician, showed that
gcd(m,n) = gcd(n, m % n).
Using Euclid's recursive algorithm, we can produce a faster
program to compute the gcd of two
numbers. The sample run shows a
running time of less than 0.1 seconds for the same input that
took 22 seconds previously. Note that the worst case input
to Euclid's gcd algorithm is two consecutive Fibonacci numbers.
- We can also implement Euclid's algorithm using a while loop
instead of recursion. (Program and
sample run.) With modern optimizing
compilers, this program isn't necessarily faster than the recursive
version. One disadvantage of not using recursion is that Euclid's
original formulation is lost.
- Another classic example of problem solving by recursion is
the Towers of Hanoi problem. Program
and sample run.
- Finally, we looked at an example of mutually recursion
where two functions call each other. In our program, the function count_alpha()
does not call itself directly, but does call the function
count_non_alphas(). Since count_non_alphas() also
calls count_alpha(), the execution of count_alpha()
does not return before another call to count_alpha() is
issued. Hence we must take great care to ensure that the recursion
terminates properly. In this program, we rely on the null character
at the end of the string to trigger the base case of the recursion.
See sample run.
23 Mar 1998 13:06:42 EST
to Spring 1998 CMSC 202 Section Homepage