As Recursion seems to pop-up every now and then I have started to write an Article on it (I will hopefully have it ready in a few days, time permitting). If anyone wants to suggest any particular aspect of or information about recursion to include please
PM me.
---------------------------
Definition
Recursion (noun)
See: Recursion
COMPUT: a programming technique where a routine performs its task by delegating part of it to another instance of itself.
Introduction
For new computer science students, the concept of recursive programming is often difficult. Recursive thinking is difficult because it almost seems like circular reasoning. It's also not an intuitive process; when we give instructions to other people, we rarely direct them recursively.
For those of you who are new to computer programming, here's a simple definition of recursion: Recursion occurs when a function calls itself directly or indirectly.
A classic example of recursion
The classic example of recursive programming involves computing factorials. In mathematics, the factorial of a nonnegative integer,
n (denoted
n!) is the product of all positive integers less than or equal to
n. For example,
5! is the same as 5*4*3*2*1, and
3! is 3*2*1.
An interesting property of a factorial is that the factorial of a number is equal to the starting number multiplied by the factorial of the number immediately below it. For example, 5! is the same as 5 * 4! You could almost write the factorial function as:
1 2 3 4
|
int factorial(int n)
{
return n * factorial(n - 1);
}
|
Listing 1. First cut factorial function
However, there is a small problem with this; it will run forever because there is no place where it stops calling itself. It therefore needs a condition to tell it to stop. Since a factorial is for positive numbers only it makes sense to stop the recursion when the input is 1 and return 1 as the result. The modified code will look like this:
1 2 3 4 5 6 7 8 9 10 11
|
int factorial(int n)
{
if(n == 1)
{
return 1;
}
else
{
return n * factorial(n - 1);
}
}
|
Listing 2. better factorial function
As you can see, as long as the initial value is above zero, this function will terminate. Note that more work will need to be done to guard again invalid initial values.
The point at with the recursion is stopped is called the base case. A base case is the bottom point of a recursive program where the operation is so trivial as to be able to return an answer directly. In the case of a factorial 1! = 1. All recursive programs must have at least one base case and must guarantee that they will hit one eventually; otherwise the program would run forever or until the program ran out of memory or stack space.
Basic steps of recursive programs
All recursive programs follows the same basic sequence of steps:
1: Initialize the algorithm. Recursive programs often need a seed value to start with.
2: Check to see whether the current value(s) being processed match the base case. If so, process and return the value.
3: Redefine the answer in terms of a smaller or simpler sub-problem or sub-problems.
4: Run the algorithm on the sub-problem.
5: Combine the results in the formulation of the answer.
6: Return the results.
Using an inductive definition
Writing provably correct programs
Comparison with Loops
Tail-recursive functions
One of the concerns that people have with regards to recursive functions is the growth of the stack space. Some of the classes of recursive functions will indeed grow the stack space linearly with the number of times they recurs. However there is a class of recursive functions where the stack size remains constant regardless of the depth of recursion, tail-recursive functions.
Tail recursion
If a function call is the last thing a function does, then this call is called a
tail-call. A recursion that uses a tail call is called tail-recursion. It would be worth looking at some examples of function calls to see exactly what is meant by a tail-call:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
int func1()
{
int a = 3;
func1(); // recursive, but not a tail call.
// processing is continued after the function returns.
a = a + 4;
return a;
}
int func2()
{
int q = 4;
q = q + 5;
return q + func1(); // func1() is not in tail position.
// There is still more work to be
// done after func1() returns
// adding q to the result
}
int func3()
{
int b = 5;
b = b + 2;
return func1(); // This is a tail-call. The return value
// of func1() is used as the return value
// for this function.
}
int func4()
{
func3(); // not in tail position
func3(); // not in tail position
return func3(); // in tail position
}
|
Listing. Tail-calls and non-tail-calls
For a call to be a true tail-call, no other operation can be performed on the result of the function before passing it back. As there is nothing left to do in the function, the actual stack frame for the function is not needed either.
Conclusion
External links
http://en.wikipedia.org/wiki/Recursion_%28computer_science%29