chapter 1 - CSUDH Computer Science

Download Report

Transcript chapter 1 - CSUDH Computer Science

CHAPTER 17
RECURSION
CHAPTER GOALS
– To learn about the method of recursion
– To understand the relationship between recursion and
iteration
– To analysis problems that are much easier to solve by
recursion than by iteration
– To learn to think recursively
– To be able to use recursive helper methods
– To understand when the use of recursion affects the
efficiency of an algorithm
•
•
•
•
Triangle Numbers
Compute the area of a triangle of width n
Assume each [] square has an area of 1
Also called the nth triangle number
Example --The third triangle number is 6
[]
[] []
[] [] []
public class Triangle
{
public Triangle(int aWidth)
{
width = aWidth;
• Outline of Triangle }
public int getArea()
Class
{
...
}
private int width;
}
• Base case: Width 1
Handling Triangle
– The triangle consists of a single square -- area is 1
– Add the code to getArea method for width 1
public int getArea()
{
if (width == 1) return 1;
}
• General case:
– Assume we know the area of the smaller,
colored triangle
– Area of larger triangle can be calculated as:
smallerArea + width
– To get the area of the smaller triangle
o make a smaller triangle and ask it for
its area
Triangle smallerTriangle =
new Triangle(width - 1);
int smallerArea =
smallerTriangle.getArea();
[]
[] []
[] [] []
[] [] [] []
Completed getArea method
• The code
• That method makes a smaller
public int getArea()
triangle of width 2
{
– It calls getArea on that triangle
if (width == 1) return 1;
• That method makes a
Triangle smallerTriangle =
new Triangle(width - 1);
smaller triangle of width 1
int smallerArea =
• It calls getArea on that
smallerTriangle.getArea();
triangle
return smallerArea + width;
– That method returns 1
• Computing the area of a
– The method returns smallerArea
triangle with width 4
+ width = 1 + 2 = 3
– getArea method makes a • The method returns smallerArea +
smaller triangle of width 3
width = 3 + 3 = 6
– It calls getArea on that
• The method returns smallerArea +
triangle
width = 6 + 4 = 10
}
Recursion
• A recursive computation solves a problem by
using the solution
of the same problem with simpler input
• For recursion to terminate,
there must be special cases for the simplest
inputs.
• To complete our Triangle example, we must
handle width <= 0
• Add this line to the getArea method
if (width <= 0)
return 0;
File Triangle.java
01: /**
02: A triangular shape composed of
stacked unit squares like this:
03: []
04: [][]
05: [][][]
06: . . .
07: */
08: public class Triangle
09: {
10: /**
11:
Constructs a triangular shape
12:
@param aWidth the width (and
height) of the triangle
13: */
14: public Triangle(int aWidth)
15: {
16:
width = aWidth;
17: }
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
/**
Computes the area of the triangle.
@return the area
*/
public int getArea()
{
if (width <= 0) return 0;
if (width == 1) return 1;
Triangle smallerTriangle = new
Triangle(width - 1);
28:
int smallerArea =
smallerTriangle.getArea();
29:
return smallerArea + width;
30: }
31:
32: private int width;
33: }
TriangleTest.java
01: import javax.swing.JOptionPane;
02:
03: public class TriangleTest
04: {
05: public static void main(String[] args)
06: {
07:
String input = JOptionPane.showInputDialog("Enter width");
08:
int width = Integer.parseInt(input);
09:
Triangle t = new Triangle(width);
10:
int area = t.getArea();
11:
System.out.println("Area = " + area);
12: }
13: }
Permutations of a String
• Design a class that lists all permutations of a string
• A permutation is a rearrangement of the letters
• The string "eat" has six permutations:
“eat”, “eta”, “aet”, “aet”, “tea”, “tae”
• Public Interface of PermutationGenerator
class PermutationGenerator
{
public PermutationGenerator(String s) { . . . }
public String nextPermutation() {. . . }
public boolean hasMorePermutations() { . . . }
}
File PermutationGeneratorTest.java
01: /**
02: This program tests the permutation generator.
03: */
04: public class PermutationGeneratorTest
05: {
06: public static void main(String[] args)
07: {
08:
PermutationGenerator generator
09:
= new PermutationGenerator("eat");
10:
while (generator.hasMorePermutations())
11:
System.out.println(generator.nextPermutation());
12: }
13: }
To Generate All Permutations
• Generate all permutations that start with 'e' , then 'a' then 't'
• To generate permutations starting with 'e', we need to find
all permutations of "at"
• This is the same problem with simpler inputs.
• Use recursion
• nextPermutaion
method returns one permutation at a
time
• PermutationGenerator remembers its state
o The string we are permuting (word)
o Position of the current character (current)
o PermutationGenerator of the substring (tailGenerator)
asks tailGenerator for its next
permutation and returns
• nextPermutation
word.charAt(current) + tailGenerator.nextPermutation();
Handling the Special Case
• When the tail generator runs out of
permutations, we need to:
o Increment the current position
o Compute the tail string that contains all
letters
except for the current one
o Make a new permutation generator for
the tail string
File PermutationGenerator.java
01: /** This class generates permutations of a word.
03: */
04: class PermutationGenerator
05: {
06: /** Constructs a permutation generator.
08:
@param aWord the word to permute
09: */
10: public PermutationGenerator(String aWord)
11: {
12:
word = aWord;
13:
current = 0;
14:
if (word.length() > 1)
15:
tailGenerator = new PermutationGenerator(word.substring(1));
16:
System.out.println("Generating " + word );
17: }
19: /**
20:
Computes the next permutation of the word.
21:
@return the next permutation
22: */
23: public String nextPermutation()
24: {
25:
if (word.length() == 1)
26:
{
current++; return word; }
31:
String r = word.charAt(current) + tailGenerator.nextPermutation();
33:
if (!tailGenerator.hasMorePermutations())
34:
{
35:
current++;
36:
if (current < word.length())
37:
{
38:
String tailString = word.substring(0, current)
39:
+ word.substring(current + 1);
40:
tailGenerator = new PermutationGenerator(tailString);
41:
}
42:
}
44:
return r;
45: }
47: /** Tests whether there are more permutations.
49:
@return true if more permutations are available
50: */
51: public boolean hasMorePermutations()
52: { return current < word.length();}
56: private String word;
57: private int current;
58: private PermutationGenerator tailGenerator;
59: }
Recursive Helper Method
• The public boolean method isPalindrone
calls helper method
isPalindrome(int start, int end)
• Helper method skips over matching letter
pairs and non-letters and calls itself
recursively
Recursive
Helper
Method
public boolean isPalindrome(int start int end)
{
//separate case for substrings of length 0 or 1
if (start>=end) return true;
//get first and last character, converted to lowercase
char first = Character.toLowerCase(text.charAt(start));
char last = Character.toLowerCase(text.charAt(end));
}
if ((Character.isLetter(first) && Character.isLetter(last))
{
if (first == last)
{
//test substring that doesn't contain the matching letters
return isPalindrome(start +1, end -1);
}
else
return false;
}
else if (!Character.isLetter(last))
{
//test substring that doesn't contain last character
return isPalindrome(start, end -1);
}
else
{
//test substring that doesn't contain first character
return isPalindrome(start + 1, end);
Fibonacci Sequence
•
Fibonacci sequence is a sequence of numbers defined by
f1 = 1,
f2 = 1
fn = fn-1 + fn-2
• First ten terms
1, 1, 2, 3, 5, 8, 13, 21, 34, 55
• The Efficiency of Recursion
• You can generate the Fibonacci series using either recursion or iteration
o Both are conceptually easy to understand and program
o Iterative solution is much faster
• Palindrome test can be implemented as either recursion or
iteration
o
o
Both are easy to program
Both run about the same speed
• Permutation generator can be solved using either recursion
or iteration
o
Recursive solution is dramatically easier to understand and
implement
o Both run at about the same speed
File
FibTest.java
01: import javax.swing.JOptionPane;
02:
03: /**
04: This program computes Fibonacci
numbers using a recursive
05: method.
06: */
07: public class FibTest
08: {
09: public static void main(String[]
args)
10: {
11:
String input =
JOptionPane.showInputDialog("E
nter n: ");
12:
int n = Integer.parseInt(input);
13:
14:
for (int i = 1; i <= n; i++)
15:
{
16:
int f = fib(i);
17:
System.out.println("fib(" + i +
") = " + f);
18:
}
19:
System.exit(0);
20: }
21:
22: /**
23:
Computes a Fibonacci number.
24:
@param n an integer
25:
@return the nth Fibonacci number
26: */
27: public static int fib(int n)
28: {
29:
if (n <= 2) return 1;
30:
else return fib(n - 1) + fib(n - 2);
31: }
32: }
Call Pattern of the Recursive
fib Method
File FibTrace.java
20: /**
01: import javax.swing.JOptionPane;
21:
Computes a Fibonacci number.
03: /** This program prints trace
messages that show how often the 22:
@param n an integer
05: recursive method for computing
23:
@return the nth Fibonacci number
Fibonacci numbers calls itself.
24: */
06: */
25: public static int fib(int n)
07: public class FibTrace
26: {
08: {
27:
System.out.println("Entering fib: n
09: public static void main(String[]
args)
= " + n);
10: {
28:
int f;
11:
String input =
29:
if (n <= 2) f = 1;
JOptionPane.showInputDialog("Ent
30:
else f = fib(n - 1) + fib(n - 2);
er n: ");
31:
System.out.println("Exiting fib: n =
12:
int n = Integer.parseInt(input);
"+n
14:
int f = fib(n);
+ " return value = " + f);
16:
System.out.println("fib(" + n + ") 32:
= " + f);
33:
return f;
17:
System.exit(0);
34: }
18: }
35: }
File FibLoop.java
19:
System.exit(0);
20: }
21:
01: import javax.swing.JOptionPane;
22: /**
03: /**
Computes a Fibonacci number.
04: This program computes Fibonacci 23:
numbers using an iterative
24:
@param n an integer
05: method.
25:
@return the nth Fibonacci number
06: */
26: */
07: public class FibLoop
27: public static double fib(int n)
08: {
28: {
09: public static void main(String[]
29:
if (n <= 2) return 1;
args)
30:
double fold = 1;
10: {
31:
double fold2 = 1;
11:
String input =
32:
double fnew = 1;
JOptionPane.showInputDialog("En 33:
for (int i = 3; i <= n; i++)
ter n: ");
{
12:
int n = Integer.parseInt(input); 34:
35:
fnew = fold + fold2;
13:
36:
fold2 = fold;
14:
for (int i = 1; i <= n; i++)
37:
fold = fnew;
15:
{
38:
}
16:
double f = fib(i);
return fnew;
17:
System.out.println("fib(" + i + 39:
40: }
") = " + f);
41: }
18:
}