recursion chapter 8. 2 chapter contents what is recursion? tracing a recursive method recursive...
Post on 19-Dec-2015
242 views
TRANSCRIPT
2
Chapter Contents
What Is Recursion?
Tracing a Recursive Method
Recursive Methods That Return a Value
Recursively Processing an Array
Recursively Processing a Linked Chain
The Time Efficiency of Recursive Methods• Time Efficiency of countDown
A Simple Solution to a Difficult Problem
A Poor Solution to a Simple Problem
3
What Is Recursion?
It is a problem-solving process involves repetitionBreaks a problem into identical but smaller problemsEventually you reach a smallest problem• Answer is obvious or trivial
Using the solution to smallest problem enables you to solve the previous smaller problemsEventually the original big problem is solvedAn alternative to iteration
• An iterative solution involves loops
5
What Is Recursion?
A method that calls itself is a recursive method
• Base case: a known case in a recursive definition. The smallest problem
• Eventually, one of the smaller problems must be the base case
/** Task: Counts down from a given positive integer.* @param integer an integer > 0 */
public static void countDown(int integer)
{ System.out.println(integer);if (integer > 1)
countDown(integer - 1);} // end countDown
6
When Designing Recursive Solution
Four questions to ask before construct recursive solutions. If you follow these guidelines, you can be assured that it will work. • How can you define the problem in terms of a smaller
problem of the same type?• How does each recursive call diminish the size of the
problem?• What instance of the problem can serve as the base
case?• As the problem size diminishes, will you reach this
base case?
7
When Designing Recursive Solution
For the method countDown, we have the following answers.• countDown displays the given integer as the
part of the solution that it contribute directly. Then call countDown with smaller size.
• The smaller problem is counting down from integer -1.
• The if statement asks if the process has reached the base case. Here, the base case occurs when integer is 1.
8
Recursive Solution GuidelinesMethod definition must provide parameter• Leads to different cases• Typically includes an if or a switch
statement
One or more of these cases should provide a non recursive solution( infinite recursion if don’t)• The base or stopping case
One or more cases includes recursive invocation• Takes a step towards the base case
9
Tracing a Recursive Method
Given: public static void countDown(int integer)
{ System.out.println(integer);if (integer > 1)
countDown(integer - 1);} // end countDown
The effect of method call countDown(3)
11
Compare Iterative and Recursive Programs
//Recursive version
public static void countDown( int integer)
{
if ( integer >= 1)
{
System.out.println(integer);
countDown(integer -1);
}
}
//Iterative version
public static void countDown( int integer)
{
while ( integer >= 1)
{
System.out.println(integer);
integer--;
}
}
12
Question?
Could you write an recursive method that skips n lines of output, where n is a positive integer. Use System.out.println() to skip one line.
Describe a recursive algorithm that draws a given number of concentric circles. The innermost or outmost circle should have a given diameter. The diameter of each of the other circles should be three-fourths the diameter of the circle just outside it.
13
Answer to skipLines
pubic static void skipLines ( int givenNumber)
{
if (givenNumber >= 1)
{
System.out.println();
skipLines(givenNumber – 1);
}
}
drawConcentricCircle( givenNumber, givenDiameter)
{
// what should be put inside??…….
}
14
Tracing a Recursive Method
Each call to a method generate an activation record that captures the state of the method’s execution and that is placed into a ADT stack. The activation-record stack remembers the history of incompleted method calls. A snapshot of a method’s state. The topmost activation record holds the data values for the currently executing method. When topmost method finishes, its activation record is popped In this way, Java can suspend the execution of a recursive method and re-invoke it when it appears on the top.
15
Tracing a Recursive Method
The stack of activation records during the execution of a call to countDown(3)… continued →
16
Tracing a Recursive Method
ctd. The stack of activation records during the execution of a call to countDown(3)
Note: the recursive method will use more
memory than an iterative method due
to the stack of activation records
Note: the recursive method will use more
memory than an iterative method due
to the stack of activation records
17
Tracing a Recursive Method
Too many recursive calls can cause the error message “stack overflow”. Stack of activation records has become full. Method has used too much memory.
Infinite recursion or large-size problems are the likely cause of this error.
18
Recursive Methods That Return a Value
Task: Compute the sum1 + 2 + 3 + … + n for an integer n > 0
public static int sumOf(int n){ int sum;
if (n = = 1)sum = 1; // base case
elsesum = sumOf(n - 1) + n; // recursive call
return sum;} // end sumOf
19
Recursive Methods That Return a Value
The stack of activation records during the execution of a call to sumOf(3)
20
Recursively Processing an Array
When processing array recursively, divide it into two pieces• Last element one piece, rest of array another• First element one piece, rest of array another• Divide array into two halves
A recursive method part of an implementation of an ADT is often private• Its necessary parameters make it unsuitable as an
ADT operation
21
Recursively Processing a Linked Chain
To write a method that processes a chain of linked nodes recursively• Use a reference to the chain's first node as the
method's parameter
Then process the first node• Followed by the
rest of the chain
public void display(){ displayChain(firstNode);
System.out.println();} // end display
private void displayChain(Node nodeOne)
{ if (nodeOne != null){ System.out.print(nodeOne.data + " ");
displayChain(nodeOne.next);}
} // end displayChain
22
Recursively Divide the Array in Halfpublic static void displayArray( int array[], int first, int last)
{
if (first == last)
System.out.print(array[first]);
else
{
int mid = (first + last) /2;
displayArray(array, first, mid);
displayArray(array, mid+1, last);
}
}
23
A Simple Solution to a Difficult Problem
The initial configuration of the Towers of Hanoi for three disks
24
A Simple Solution to a Difficult Problem
Rules for the Towers of Hanoi game
1. Move one disk at a time. Each disk you move must be a topmost disk.
2. No disk may rest on top of a disk smaller than itself.
3. You can store disks on the second pole temporarily, as long as you observe the previous two rules.
25
A Simple Solution to a Difficult Problem
The sequence of moves for solving the Towers of Hanoi problem with three
disks.
Continued →
26
A Simple Solution to a Difficult Problem
(ctd) The sequence of moves for solving the
Towers of Hanoi problem with three disks
27
A Simple Solution to a Difficult Problem
The smaller problems in a recursive solution for
four disks
28
A Simple Solution to a Difficult Problem
Algorithm for solution with 1 disk as the base case
Algorithm solveTowers(numberOfDisks, startPole, tempPole, endPole)
if (numberOfDisks == 1)
Move disk from startPole to endPole
else
{
solveTowers(numberOfDisks-1, startPole, endPole, tempPole)
Move disk from startPole to endPole
solveTowers(numberOfDisks-1, tempPole, startPole, endPole)
}
29
Recursion Efficiency
How many moves occur for n disks?
m(1) = 1 for n>1, two recursive calls to solve problems that have n-1 disks.
m(n) = m(n-1) + m(n-1) +1 = 2*m(n-1) +1
Let’s evaluate the recurrence for m(n) for a few values of n:
m(1) =1; m(2) = 3; m(3) = 7;m(4) = 15; m(5) = 31; m(6) = 63….
m(n) = 2^n -1
30
Mathematical Induction
Prove this conjecture m(n) = 2^n -1 by using mathematical induction:
We know that m(1) =1, which equals to 2^1-1=1, so the conjecture is true for n =1.
Now assume that it is true for n=1,2,…,k, and consider m(k+1).
m(k+1) = 2*m(k) +1 (use the recurrence relation)
=2*(2^k-1) +1 = 2^(k+1) -1 ( we assume that m(k) = 2^k-1)
Since the conjecture is true for n=k+1, it is true for all n>=1
31
Mathematical Induction
Assume you want to prove some statement P, P(n) is true for all n starting with n = 1. The Principle of Math Induction states that, to this end, one should accomplish just two steps:1). Prove that P(1) is true. 2). Assume that P(k) is true for some k. Derive from here that P(k+1) is also true.
look P(1) is true and implies P(2). Therefore P(2) is true. But P(2) implies P(3). Therefore P(3) is true which implies P(4) and so on.
32
Multiplying Rabbits (The Fibonacci Sequence)
“Facts” about rabbits• Rabbits never die• A rabbit reaches sexual maturity exactly two
months after birth, that is, at the beginning of its third month of life
• Rabbits are always born in male-female pairs• At the beginning of every month, each
sexually mature male-female pair gives birth to exactly one male-female pair
33
Multiplying Rabbits (The Fibonacci Sequence)
Problem• How many pairs of rabbits are alive in month n?• Month Month No calculation rabbit couples • January 1 1 + 0 = 1• February 2 1 + 0 = 1• March 3 1 + 1 = 2• April 4 2 + 1 = 3• May 5 3 + 2 = 5• June 6 5 + 3 = 8• July 7 8 + 5 = 13• August 8 13 + 8 = 21
Recurrence relationrabbit(n) = rabbit(n-1) + rabbit(n-2)
34
A Poor Solution to a Simple Problem
Fibonacci numbers• First two numbers of sequence are 1 and 1• Successive numbers are the sum of the
previous two• 1, 1, 2, 3, 5, 8, 13, …
This has a natural looking recursive solution• Turns out to be a poor (inefficient) solution
35
A Poor Solution to a Simple Problem
The recursive algorithm
Algorithm Fibonacci(n)if (n <= 1)
return 1else
return Fibonacci(n-1) + Fibonacci(n-2)
36
A Poor Solution to a Simple Problem
The computation of the Fibonacci number F6 (a) recursively; (b) iteratively
Time efficiency grows exponentially with n,
which is k^n
Time efficiency grows exponentially with n,
which is k^n
Iterative solution is O(n)Iterative solution is O(n)
int fib(int n) { int f[n+1]; f[1] = f[2] = 1; for (int i = 3; i <= n; i++) f[i] = f[i-1] + f[i-2]; return f[n]; }