Problem :
Define "recursion". What does it mean for a function to be
recursive?
Recursion is an algorithmic technique where a function, in
order to accomplish a task, calls itself with some part of the
task. A recursive function calls itself on a simpler version
of the problem in an attempt to simplify the problem to a point
where it can be solved. With this smaller problem solved, it
can work backwards to solve each slightly larger problem until
the entire problem has been solved.
Problem :
Your boss asks you to write a function to sum up all of the
numbers between some high and low value. You decide to write
two different versions of the function, one recursive and one
iterative.
1) Write them.
The next morning you come into work and your boss calls you
into his office, unhappy at how slow both of your functions
work, compared to how the problem could be solved.
2) How else could you solve this problem?
1a) Iteratively:
int sum_nums(int low, int high)
{
int i, total=0;
for(i=low; i<=high; i++) total+=i;
return total;
}
1b) Recursively:
int sum_nums(int low, int high)
{
if (low == high) return high;
else return low + sum_nums(low+1, high);
}
2) Certain mathematical functions have closed form expressions;
this means that there is actually a mathematical expression
that can be used to explicitly evaluate the answer, thereby
solving the problem in constant time, as opposed to the linear
time it takes for the recursive and iterative versions.
int sum_nums(int low, int high)
{
return (((high*(high+1))/2) - (((low-1)*low)/2);
}
Problem :
What is a base case? Why must a recursive function have a base
case? Can a function be written recursively if a base case is
not known?
The base case(s), or halting case(s), are the conditions under
which a recursive function stops recurring. The base case is
the small problem we know how to solve. Every recursive
function must have a base case in order to stop (the base case
is the point at which the recursion halts); if a base case did
not exist, the function would keep recurring until it exhausted
the system's resources and most likely crashed your program.
If a base case is not known, a function cannot be written
recursively.
Problem :
What is wrong with the following function?
int factorial(int n)
{
if (n<=1) return 1;
else if (n<0) return 0;
else return factorial(n-1) * n;
}
The first two if statements should be switched. This function
works fine if the function is called on valid input (
n > = 0).
But if it is called on invalid input (
n < 0), the function
will incorrectly return
1.
Problem :
Your research assistant has come to you with the following two
functions:
int factorial_iter(int n)
{
int fact=1;
if (n<0) return 0;
for( ; n>0; n--) fact *= n;
return(fact);
}
and
int factorial_recur(int n)
{
if (n<0) return 0;
else if (n<=1) return 1;
else return n * factorial_recur(n-1);
}
He claims that the
factorial_recur() function is more efficient because
it has fewer local variables and thus uses less space. What do you tell him?
Every time the recursive function is called, it takes up stack
space (we'll discuss this more exhaustively in the section) and
space for its local variables are set aside. So actually, the
recursive version takes up much more space overall than does
the iterative version.
Problem :
As you probably noticed, the size of n! grows quickly as n
increases. As such, you will probably reach a point were your
computer can no longer represent the value of n! (unless you
are using language with a big number library or unlimited
integer precision). Determine what the largest value of n is
for which the computer can accurately compute n!.
This depends on your computer. Try running the factorial
function with increasing values of
n and see where something
strange happens.
Problem :
Back to the problem of programming Data to walk. Write a function
void walk(int n) that takes n steps. You should use the
void take_one_step() function as a helper function.
void walk(int n)
{
if (n>=1) take_one_step();
if (n>1) walk(n-1);
}