Recursion Example 1

1
CS 1120 – Computer Science II
Recursion
(Ch.15)
Many slides modified by Prof. L. Lilien
(even many without an explicit message).
Slides added by L.Lilien are © 2006-2009 Leszek T. Lilien.
Permision to use for non-commercial purposes slides added by
L.Lilien’s will be gladly granted upon a written (e.g., emailed)
request.
 2002-2010 Prentice Hall. All rights reserved.
2
Recursion
• Recursive methods - call themselves:
– Directly
– Indirectly
• Call others methods which call it
• Continually breaks problem down to simpler forms
– Each method call divides the problem into two pieces:
• A piece that the method knows how to do
• A recursive call (a.k.a. recursion step) that solves a smaller
problem
• In other words, each recursive method:
– Waits till recursive call made by it finishes
– Then finishes itself
• The method must converge in order to end recursion
– Must include a “terminating condition” (see below)
 2002-2010 Prentice Hall. All rights reserved.
Recursion Example 1: Factorials
• Recursive formula for factorial calculation:
n! = n . (n – 1)! Termination conditions: 1! = 1
Fig. 7.13 |
Recursive
evaluation of 5!
 2002-2010 Prentice Hall. All rights reserved.
0! = 1
3
import javax.swing.JOptionPane;
/**
This program demonstrates the recursive factorial method.
*/
Sample
I/O:
public class FactorialDemo
{
public static void main(String[] args)
{
String input;
// To hold user input
int number;
// To hold a number
// Get a number from the user.
input = JOptionPane.showInputDialog("Enter a " + "nonnegative integer:");
number = Integer.parseInt(input);
// Display the factorial of the number.
JOptionPane.showMessageDialog(null, number + "! is " + factorial(number));
}
System.exit(0);
Main calls the factorial
method to get the result
/**
The factorial method uses recursion to calculate the factorial of its
argument, which is assumed to be a nonnegative number.
@param n The number to use in the calculation.
Must be static since it is called by a static
@return
The factorial of n.
method (main). Recall that a static method
can only use/call static fields/methods.
*/
}
private static int factorial(int n) The recursion ends when
{
the number is 0
if (n == 0)
return 1;
// Base case
else
return n * factorial(n - 1);
}
Factorial calls itself
// end of class FactorialDemo
 2002-2010 Prentice Hall. All rights reserved.
recursively here
4
5
• Run FactorialDemo and watch Call Stack in Debugging window
1) Open Output window, Debugging>>Variables window
2) Set up breakpoint in line 37 (left click on left gray margin)
3) Select Debug>>Debug Main Project
4) Enter input (e.g., 4) – as requested
5) Open Hidden Source Calls folder (bottom of the Debugging window)
6) Look at value of n in Variable window
7) Select Debug>>Continue (or hit F5)
8-N) Repeat 5-7 till execution finishes
• Final notes for FactorialDemo
• I bet that you could write a program calculating n! for n = 0, 1, …, 10
without using recursion that is faster and requires less memory (a more
efficient program)
• We use recursion here (in this case less efficient) for educational purposes
• So that you can learn how to use recursion in these cases when using
recursion is the best way to solve a problem
© Leszek
T. Lilien, 2009-2012
 2002-2010
Prentice
Hall. All rights reserved.
6
** READ LATER**
Recursion (Cont.)
Common Programming Error
Infinite recursion (error!) occurs when the programmer either:
1) omits the base case (terminating condition), or
2) writes the recursion step incorrectly so that it does not converge on
the base case
Infinite recursion will eventually exhaust available memory.
This error is analogous to the problem of an infinite loop in an
iterative (nonrecursive) solution.
 2002-2010 Prentice Hall. All rights reserved.
7
Recursion Example 2: The Fibonacci Numbers
• Fibonacci Numbers (a.k.a. Fibonacci Sequence)
– Recursion used to calculate F(n):
• F(0) = 0
Two terminating conditions.
• F(1) = 1
• F(n) = F(n - 1) + F(n - 2)
F( 3 )
}
• Example –
– Set of recursive calls
to method Fibonacci
return F( 2 )
[from Fig. 6.17 (ed.1)]
return F( 1 )
return 1
 2002-2010 Prentice Hall. All rights reserved.
+
F( 0 )
return 0
+
F( 1 )
return 1
import javax.swing.JOptionPane;
8
/**
This program demonstrates the recursive fib method.
*/
public class FibNumbers
{
public static void main(String[] args)
{
String input;
// To hold user input
int number;
// To hold a number
// Get a number from the user.
input = JOptionPane.showInputDialog("Enter a " + "nonnegative integer:");
number = Integer.parseInt(input);
}
// Display the Fibonacci number for the input.
JOptionPane.showMessageDialog(null,
"Fibonacci(" + number + ") is " + fib(number));
System.exit(0);
Main calls the recursive
fib method to get result
/**
*/
The fib method calculates the nth number in the Fibonacci series.
@param n The nth number to calculate.
Must be static since it is called by a static method (main).
@return The nth number.
public static int fib(int n)
{
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
} // end of class FibNumbers
 2002-2010 Prentice Hall. All rights reserved.
The recursion ends (“return”)
when the number is 0 or 1
Fibonacci calls itself twice, to get the
result as the sum of the two previous
Fibonacci numbers
Output example 1:
Output example 2:
© Leszek
T. Lilien, 20012
 2002-2010
Prentice
Hall. All rights reserved.
9
10
• Run FibNumbers and watch Call Stack in Debugging window
1) Open Output window, Debugging>>Variables window
2) Set up breakpoint in line 33 (left click on left gray margin)
3) Select Debug>>Debug Main Project
4) Enter input (e.g., 6) – as requested
5) Open Hidden Source Calls folder (bottom of the Debugging window)
6) Look at value of n in Variable window
7) Select Debug>>Continue (or hit F5)
8-N) Repeat 5-7 till execution finishes
• Final notes for FibNumbers (analogous as for n!)
• I bet that you could write a program calculating Fibonacci(n) without using
recursion that is faster and requires less memory (a more efficient program)
• We use recursion here (in this case less efficient) for educational purposes
• So that you can learn how to use recursion in these cases when using
recursion is the best way to solve a problem
© Leszek
T. Lilien, 2009
 2002-2010
Prentice
Hall. All rights reserved.
11
Recursion vs. Iteration
• Iteration
– Uses repetition structures
• while, do/while, for, foreach
– Continues until counter fails repetition condition
• Recursion
– Uses selection structures
• if, if/else, switch
– Repetition through method calls
– Continues until a termination case reached (e.g., fib(0) or
fib(1) for Fibonacci numbers progam)
– Creates duplicates of the variables
• Can consume a lot of memory and processor speed
 2002-2010 Prentice Hall. All rights reserved.
12
Recursion Example 3: Towers of Hanoi
• Background:
– In a temple in the Far East, priests are attempting to move a stack of 64
disks from one peg to another
–
The legend: The world will end when
the priests complete their task
– The initial stack of 64 disks is
threaded onto Peg 1 and
arranged from bottom to top
by decreasing size
– The priests are attempting to move the stack from this peg to Peg 3 under
the constraints that:
• Exactly one disk is moved at a time and
• At no time may a larger disk be placed above a smaller disk
– Peg 2 is available for temporarily holding disks
 2002-2010 Prentice Hall. All rights reserved.
Towers of Hanoi – Cont.
13
• Write an application to solve the Towers of Hanoi problem.
• Allow the user to enter the number of disks.
• Use a recursive Tower method with four parameters:
a) the number of disks to be moved,
b) the id of the initial peg (on which these disks are initially threaded),
c) the id of the final peg (to which this stack of disks is to be moved),
d) the id of the temporary peg (to be used as a temporary holding area).
• The application should display the precise instructions it will take to move the
disks from the starting peg to the destination peg.
— Example: To move a stack of 3 disks from Peg 1 to Peg 3, the
application should display the following series of moves:
1 --> 3 (This notation means “Move the top disk from Peg 1 to Peg 3.”)
1--> 2
3 --> 2
1 --> 3
2 --> 1
2 --> 3
1 --> 3
 2002-2010 Prentice Hall. All rights reserved.
Towers of Hanoi – Cont.
• Developing an algorithm that displays the precise sequence of
peg-to-peg disk transfers
• If we were to approach this problem with conventional methods (e.g.
using iteration), we would rapidly find ourselves hopelessly knotted up
in managing the disks
• If we attack the problem with recursion in mind, it immediately becomes
quite easy to solve
 2002-2010 Prentice Hall. All rights reserved.
14
Towers of Hanoi – Cont.
• Design -- Approach:
1) Moving n disks from Peg 1 to Peg 3, using Peg 2 as a temporary
peg can be viewed recursively in terms of moving only n – 1
disks:
a) Move n – 1 disks from Peg 1 to Peg 2, using Peg 3 as a
temporary peg
b) Move the last disk (the largest) from Peg 1 to Peg 3
c) Move the n – 1 disks from Peg 2 to Peg 3, using Peg 1 as a
temporary peg
2) Terminating condition (base case ): The process ends when the last
task requires moving n = 1 disks
This last task is accomplished by simply moving the disk (from the
initial to the final peg) without the
need for a temporary holding area
 2002-2010 Prentice Hall. All rights reserved.
15
import java.util.Scanner;
Towers of Hanoi Code
/**
Application solves the Towers of Hanoi problem using recursion.
*/
public class TowerOfHanoi
{
static public void main(String[] args)
{
// Create a Scanner object for keyboard input.
Scanner keyboard = new Scanner(System.in);
// Get the number of disks from the user.
System.out.print("Enter the number of disks for Towers of Hanoi: ");
int nrDisks = keyboard.nextInt();
// Call the recursive method ToH (Towers of Hanoi)
ToH(nrDisks, 1, 3, 2);
} // end method main
main calls the recursive ToH method to
get the sequence of disk moves.
/**
The ToH method displays all disk moves.
@param num The number of discs to move.
@param fromPeg The peg to move from.
@param toPeg The peg to move to.
@param tempPeg The temporary peg.
Method main calls the
recursive method Hanoi
to get result
*/
private static void ToH(int num, int fromPeg, int toPeg, int tempPeg)
{
if (num > 0)
{
ToH(num - 1, fromPeg, tempPeg, toPeg);
ToH calls itself twice, to get
System.out.println("Move a disc from peg " +
fromPeg + " to peg " + toPeg);
the result s (see pseudocode)
ToH(num - 1, tempPeg, toPeg, fromPeg);
}
} // end method ToH
} 2002-2010
// end Prentice
class Hall.
TowerOfHanoi

All rights reserved.
16
Towers of Hanoi – 2 Sample Outputs
Peg A
Peg B
Peg C
 2002-2010 Prentice Hall. All rights reserved.
17
Towers of Hanoi – Cont.
• Note: Don’t try to run the following program for values larger
than 12 – you will use a lot of time and display (or printout)
space.
• We’ll learn later how complexity theory explains this
 2002-2010 Prentice Hall. All rights reserved.
18
19
• Final notes for Towers of Hanoi
• I bet that you could not write a program solving Towers of Hanoi without
using recursion (even a less efficient one)
• We use recursion here not just for educational purposes
• This is an example of a problem when using recursion is the best way
to solve a problem
© Leszek
T. Lilien, 2009
 2002-2010
Prentice
Hall. All rights reserved.
20
The End
 2002-2010 Prentice Hall. All rights reserved.