Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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: }