|
|
|
|
We have already seen that a method in a class
can call other methods, either in the same or other classes |
|
• However a method in a class can also call itself |
|
• This self-referential behavior is known as recursion |
|
• Recursion is an extremely powerful technique
for expressing certain complex programming tasks, as it provides a very
natural way to decompose problems |
|
• Despite this, there are costs associated with
recursion and the careful programmer will always be aware of these |
|
|
|
|
|
|
|
|
|
|
The factorial of N is the product of the first N positive integers: |
|
N * (N – 1) * (N – 2 ) * . . . * 2 * 1 |
|
The factorial of N can be defined recursively as |
|
|
|
|
An recursive method is a method that contains a statement (or statements) that
makes a call to itself. |
|
Implementing the factorial of N recursively will
result in the following method. |
|
|
|
|
|
Each recursive call to the method creates a “new
copy” of the method – all the local variables are created again |
|
• The compiler keeps track of them all so that
the programmer cannot mix them up |
|
factorial(4)has a parameter n equal to 4 |
|
factorial(3) has its own parameter n, equal to 3 |
|
factorial(2) has its own parameter n, equal to 2 |
|
factorial(1) has its own parameter n, equal to 1 |
|
• This means that you should not use recursion
to replace |
|
straightforward iteration (like factorial),
particularly if the loops are performed thousands or millions of times. |
|
|
|
|
• Every valid recursive method definition needs
two parts – the base case and the recursive part |
|
• The base case gives the value that the method
should return for some specified parameters |
|
– Usually the base case represents some sort of
“trivial” case, such as a zero parameter or an empty list etc. |
|
• The recursive part expresses the value to be
returned in terms of another call to the same method, but with different
parameters |
|
– To work correctly, the “different parameters”
must be closer to the base case (in some sense) |
|
|
|
|
public long factorial(int n) { |
|
return n*factorial(n-1); |
|
if (n == 0) { |
|
return 1; |
|
} |
|
} |
|
You must put the base case before the recursive |
|
part of the definition or bad things will happen
– in this case a stack overflow will result! |
|
|
|
|
There is no need to have just one base case |
|
• The (mathematical) definition of the Fibonacci
numbers is a recursive definition with two base cases |
|
|
|
|
|
• This gives the sequence 1, 1, 2, 3, 5, 8, 13,
21, 34, … |
|
|
|
|
|
|
public int fibonacci(int n) { |
|
if (n == 0 || n == 1) { |
|
return 1; |
|
} |
|
else { |
|
return fibonacci(n-1)+fibonacci(n-2); |
|
} |
|
} |
|
• This looks fine, but in fact is disastrously |
|
slow because it unnecessarily repeats some |
|
calculations over and over again! |
|
|
|
|
Here’s a sample recursive method for
non-numerical application. The routine lists the names of all files in a
given directory and its subdirectories. |
|
|
|
|
Here’s the second sample recursive method for
nonnumerical application. The routine lists all anagrams of a given word. |
|
|
|
|
The basic idea is to recurse on a sub-word after
every rotation. Here’s how: |
|
|
|
|
|
What does the method funny return, in terms of
its argument? This code does compile and run.
Recall that substr(a, b)creates a string from the original, using indices
from A to b-1 .
private
static String funny( String thing ) {
String result =
thing;
int last = thing.length() -
1;
if ( last > 0
) {
result = thing.charAt(
last )
+ funny(
thing.substring( 0, last ) );
} |
|
Show the output that would result from executing
the following instruction in the "main" method:
System.out.println( funny("hello") ); |
|
|
|
|
Write a recursive or non-recursive method
powerOfTwo that computes 2 to the power of n. You may assume that n is a positive integer. You are not allowed to use the Math
class. |
|