Chapter 23 - Recursion revisited. After you have mastered the material in this chapter, you will be able to: Take a fresh look at recursion, learn when to use recursion and when to stay away from it, learn to prove the correctness of recursive methods, get ready for the Game of Hex lab.
Java Methods Object-Oriented Programming and Data Structures 2nd AP edition with GridWorld Maria Litvin ● Gary Litvin C H T A T R P P E R Recursion Revisited Copyright © 2011 by Maria Litvin, Gary Litvin, and Skylight Publishing All rights reserved Objectives: • Take a fresh look at recursion • Learn when to use recursion and when to stay away from it • Learn to prove the correctness of recursive methods • Get ready for the Game of Hex lab 232 Recursion Basics • A recursive method has a base case (or several base cases) and a recursive case In the base case, there are no recursive calls In the recursive case, the method calls itself, but for a “smaller” task • Recursive calls must eventually converge to a base case, when recursion stops 233 Example public String reverse (String s) { Base case if (s.length() < 2) (nothing to do) return s; return reverse (s.substring (1)) + s.charAt(0); } Recursive case ABCD Take substring A BCD Reverse substring A DCB Append the first char DCBA 234 Need x7 Example / == public double pow (double x, int n) { Base case if (n == 0) return 1.0; double y = pow (x, n / 2); y *= y; if ( n % != ) y *= x; return y; } Recursive case First get y = x3 Then square y*y = x6 is odd, so y *= x Caution: NOT double y = pow(x, n / 2) *pow(x, n / 2); 235 ArrayList fruits = new ArrayList ( ); fruits.add ("apples"); fruits.add ("bananas"); Example ArrayList snacks = new ArrayList ( ); snacks.add ("chips"); snacks.add ("pretzels"); ArrayList food = new ArrayList ( ); food.add ("Fruits"); food.add (fruits); food.add ("Snacks"); food.add (snacks); Recursive calls to ArrayList’s toString method take place here System.out.println (food); Output: [Fruits, [apples, bananas], Snacks, [chips, pretzels]] 236 Example public boolean degreeOfSeparation ( Set people, Person p1, Person p2, int n) { Base case if (n == 1) { return p1.knows (p2); } Recursive else case { for (Person p : people) { if (p1.knows (p) && degreeOfSeparation (people, p, p2, n-1)) return true; } return false; } } p1 p p2 237 When to Use Recursion • Recursion is especially useful for handling nested structures and branching processes 238 Example public void traverse (TreeNode root) { if (root != null) Recursive case { display (root.getValue ( )); traverse (root.getLeft ( )); traverse (root.getRight ( )); } } 2 239 Example ABCD DBC A ABCD public void permutations (StringBuffer str, int n) { if (n 2) { next = f1 + f2; f1 = f2; f2 = next; n ; } return f2; } fibonacci (100) takes a few microseconds to run 2314 Recursion and Math Induction • Recursive methods are hard to trace in a conventional way • A recursive method can be proven correct using math induction • Other properties of a recursive method (running time, required space, etc.) can be obtained by using math induction 2315 Math Induction Basics • You have a sequence of statements P1, P2, P3, Pn-1 , Pn , • Suppose P1 is true (“base case”) • Suppose you can prove that for any n > 1, if P1, Pn-1 are all true then Pn must be true, It is often possible to prove that if Pn-1 too is true then Pn is also true • Then you can conclude (“by math induction”) that Pn is true for any n 2316 Math Induction Example: Prove that for any n 1 + + + + 2n = 2n+1 - Proof: If n = then + = 22 - Suppose (induction hypothesis) + + + + 2n-1 = 2n - Then + + + + 2n = (1 + + + 2n-1) + 2n = (2n - 1) + 2n = 2·2n - = 2n+1 - By math induction, the equality is true for any n 1, q.e.d 2317 Math Induction and Recursion public String reverse (String s) { if (s.length( ) < 2) return s; return reverse (s.substring(1)) + s.charAt(0); } Let us verify that this method works, that is, reverse(s) indeed returns the reverse of s We will use math induction “over the length of s.” To be continued 2318 Proof public String reverse (String s) { if (s.length < 2) return s; Let n = s.length(); If n = or n = then reverse return reverse (s.substring(1)) + s.charAt(0); } works because the string remains unchanged Suppose (induction hypothesis) reverse works for any string of length n-1 Then it works for s.substring(1) So we reverse that substring and then append the first char of s at the end We get the reverse of s By math induction, reverse works for a string of any length, q.e.d 2319 The Tower of Hanoi • Objective: move the tower from one peg to another, moving one disk at a time and never placing a larger disk on top of a smaller one; you can use the spare peg • This puzzle was invented by Franỗois Edouard Anatole Lucas and published in 1883 23ư20 The Tower of Hanoi: Recursive Solution For n disks: • If n = 1, just move the disk to the desired peg • If n > Move the top n-1 disks to a spare peg (recursive step) Move the bottom disk to the desired peg Move all n-1 disks from the spare to the desired peg (recursive step) 2321 The Game of Hex B W W B • Two players take turns placing a stone of their color • Objective: connect your pair of the opposite sides of the board with stones of your color 2322 The Game of Hex (cont’d) • Computer representation of the board in a 2-D array W B B Each cell has six “logical” neighbors W 2323 The Game of Hex (cont’d) • To detect a win, determine whether any “blob” (connected group of stones) touches the opposite sides 2324 The Game of Hex (cont’d) • This kind of task falls into the category of “area fill” tasks 2325 Review: • What is recursion? • How is recursion implemented in a computer? • What kinds of applications especially benefit from recursion? • Give an example of a task that can be programmed recursively and also, as easily, with iterations 2326 Review (cont’d): • Give an example of a task that would be rather hard to program without recursion • Give an example of a method that is too slow in a naïve recursive implementation • What mathematical tool is very useful for understanding recursive methods and proving them correct? 2327 Review (cont’d): • What is the number of moves necessary to solve the Tower of Hanoi puzzle with 1, 2, 3, , n disks? How would you prove your hypothesis? • Can you come up with an idea for a recursive algorithm for “area fill”? 2328 ... 22 - Suppose (induction hypothesis) + + + + 2n-1 = 2n - Then + + + + 2n = (1 + + + 2n-1) + 2n = (2n - 1) + 2n = 2·2n - = 2n+1 - By math induction, the equality is true for any n 1, q.e.d 23? ?17... (str); else Recursive case { for ( int i = 0; i < n; i++ ) { swap (str, i, n-1); permutations (str, n-1); 1-4 swap (str, n-1, i); } } } ABCD ADC B ABCD ABCD ABD C ABCD ABCD ABC D ABCD BCD A CBD A... degreeOfSeparation (people, p, p2, n-1)) return true; } return false; } } p1 p p2 23? ?7 When to Use Recursion • Recursion is especially useful for handling nested structures and branching processes