Presentation is loading. Please wait.

Presentation is loading. Please wait.

Java Methods Recursion Revisited Object-Oriented Programming

Similar presentations


Presentation on theme: "Java Methods Recursion Revisited Object-Oriented Programming"— Presentation transcript:

1 Java Methods Recursion Revisited Object-Oriented Programming
and Data Structures 2nd AP edition  with GridWorld Maria Litvin ● Gary Litvin Recursion will be revisited again in the next chapter (Chapter 24, Binary Trees). Recursion Revisited Copyright © 2011 by Maria Litvin, Gary Litvin, and Skylight Publishing. All rights reserved.

2 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 Another objective is to show that recursion is fun, when used properly.

3 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 “Infinite” recursion eventually overflows the system stack, and the program crashes.

4 Example 1 ABCD public String reverse (String s) {
Take substring public String reverse (String s) { if (s.length() < 2) return s; return reverse (s.substring (1)) + s.charAt(0); } A BCD Base case (nothing to do) Reverse substring A DCB Append the first char This task can be handled as easily without recursion. Recursive case DCBA

5 Example 2 public double pow (double x, int n) { if (n == 0)
Need x7 Example 2 7 / 2 == 3 First get y = x3 public double pow (double x, int n) { if (n == 0) return 1.0; double y = pow (x, n / 2); y *= y; if ( n % 2 != 0 ) y *= x; return y; } Base case Then square y*y = x6 Recursive case 7 is odd, so y *= x If we wrote double y = pow(x, n/2) * pow(x, n/2); we would get branching recursion and the code would become very inefficient. Caution: NOT double y = pow(x, n / 2) *pow(x, n / 2);

6 Example 3 ArrayList fruits = new ArrayList ( ); fruits.add ("apples");
fruits.add ("bananas"); 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); System.out.println (food); Recursive calls to ArrayList’s toString method take place here This is an example of dealing with nested structures recursively. This code is a little sloppy: it uses “raw” ArrayList and will cause warnings in Java 5. In a more precise implementation, we would define an interface FoodItem and two classes that implement it: SimpleFoodItem and CompositeFoodItem (which could extend ArrayList<FoodItem>). Then fruits, snacks, and food would become CompositeFoodItems. Output: [Fruits, [apples, bananas], Snacks, [chips, pretzels]]

7 Example 4 public boolean degreeOfSeparation ( p1
Set<Person> people, Person p1, Person p2, int n) { if (n == 1) return p1.knows (p2); } else for (Person p : people) if (p1.knows (p) && degreeOfSeparation (people, p, p2, n-1)) return true; return false; p1 p Base case p2 Recursive case This solution is short, but not very efficient. A more efficient solution is discussed in one of the exercises in the book.

8 When to Use Recursion Recursion is especially useful for handling nested structures and branching processes In a recursive structure, parts have the same organization as the whole.

9 Example 5 1 public void traverse (TreeNode root) { 2 if (root != null)
display (root.getValue ( )); traverse (root.getLeft ( )); traverse (root.getRight ( )); } 2 Recursive case 1 2 3 3 Trees are the subject of the next chapter. This is called preoder traversal, because the root is processed first. There are other traversal sequences  they are discussed in Chapter 24.

10 Example 6 1 ABCD DBC A ABCD public void permutations
BCD A CBD A CDB A DCB A BDC A DBC A ABCD DBC A ABCD public void permutations (StringBuffer str, int n) { if (n <= 1) System.out.println (str); else for ( int i = 0; i < n; i++ ) swap (str, i, n-1); permutations (str, n-1); swap (str, n-1, i); } 2 DCA B CDA B CAD B ACD B DAC B ADC B ABCD ADC B ABCD Recursive case 3 BDA C DBA C DAB C ADB C BAD C ABD C ABCD ABD C We swap the i-th character with the last one, make all permutations of the first (n – 1) characters (recursively), then swap back the last and the i-th characters to restore the original string. ABCD 1 - 4 BCA D CBA D CAB D ACB D BAC D ABC D 4 ABCD ABC D ABCD

11 Use Recursion Do Not Use Recursion
When it significantly simplifies code without significant perfomance penalty Do Not Use Recursion When a method allocates large local arrays When a method unpredictably changes fields When iterative solutions is just as simple If n, the size of the task, is large, it may be not practical to use a recursive algorithm with subtasks of size n–1 because the depth of recursion will be proportional to n. Algorithms with subtasks of size n/2 are OK, because the depth of recursion will be proportional to log n. We should try to use algorithms that split the task into two or more subtasks of roughly equal size.

12 Just As Easy With Iterations
public String reverse (String s) { if (s.length () < 2) return s; return reverse ( s.substring(1)) + s.charAt(0); } public String reverse (String s) { String r = ""; for (int i = s.length( ) - 1; i >= 0; i--) r += s.charAt (i); return r; } “Linear” processes usually can be handled easily with iterations  no need for recursion.

13 Not Easy Without Recursion
Need your own stack to do this without recursion public void traverse (TreeNode root) { if (root != null) display (root.getValue ()); traverse (root.getLeft ()); traverse (root.getRight ()); } We have an example of a non-recursive solution for this, using a stack, in Chapter 22. Rule of thumb: use recursion when the process is branching, that is, when the method is called recursively more than once or within a loop

14 Very Inefficient Recursive Code
public long fibonacci (int n) { if (n < 2) return 1; else return fibonacci (n-2) + fibonacci (n-1); } public long fibonacci (int n) { long f1 = 1, f2 = 1, next; while (n > 2) next = f1 + f2; f1 = f2; f2 = next; n--; } return f2; The total number of steps in the recursive Fibonacci method is greater than C*(3/2)n. fibonacci (100) takes 50 years to run fibonacci (100) takes a few microseconds to run

15 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. The concepts of recursion and math induction are closely related.

16 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, too. Then you can conclude (“by math induction”) that Pn is true for any n  1 It is often possible to prove that if Pn-1 is true then Pn is also true. The assumption that P1, ... Pn-1 are true gives powerful tools for proving Pn.

17 Math Induction Example:
Prove that for any n  1 n = 2n+1 - 1 Proof: 1. If n = 1 then = 2. Suppose (induction hypothesis) n-1 = 2n - 1 Then n = ( n-1) + 2n = (2n - 1) + 2n = 2·2n - 1 = 2n+1 - 1 By math induction, the equality is true for any n  1, q.e.d. Try to prove on your own using math induction that, for any n  1, n = n(n+1)/2.

18 Math Induction and Recursion
public String reverse (String s) { if (s.length( ) < 2) return s; return reverse (s.substring(1)) + s.charAt(0); } If you are given a “mystery” recursive method and asked what it does, make an educated guess, then verify it using math induction. 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... 

19 Proof Let n = s.length(); 1. If n = 0 or n = 1 then reverse
public String reverse (String s) { if (s.length < 2) return s; return reverse (s.substring(1)) + s.charAt(0); } Proof Let n = s.length(); 1. If n = 0 or n = 1 then reverse works because the string remains unchanged 2. 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. Using math induction we can also prove properties of recursive code, for example, how much time it takes to execute.

20 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 The “legend” that accompanied the game stated that in Benares, India, there was a temple with a dome that marked the center of the world. The Hindu priests in the temple moved golden disks between three diamond needles. God placed 64 gold disks on one needle at the time of creation and, according to the legend, the universe will come to an end when the priests have moved all 64 disks to another needle.

21 The Tower of Hanoi: Recursive Solution
For n disks: If n = 1, just move the disk to the desired peg. If n > 1 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). Our goal here is to move the tower from the left peg to the middle peg. In recursive calls, different pegs serve as “spare.” You can find numerous animations of Tower of Hanoi on the Internet.

22 The Game of Hex 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 Each player is assigned a pair of opposite sides of the board before the game starts. An interesting property of this game is that it never ends in a draw. Any board filled with white and black stones has either W‑W sides connected with white stones or B‑B sides connected with black stones.

23 The Game of Hex (cont’d)
Computer representation of the board in a 2-D array Each cell has six “logical” neighbors In computer applications, a cell inside a rectangular grid usually has 4 neighbors or 8 neighbors (if you count the neighbors attached diagonally). Here each cell has 6 neighbors: two diagonal neighbors out of four are included.

24 The Game of Hex (cont’d)
To detect a win, determine whether any “blob” (connected group of stones) touches the opposite sides Strategies for quitting early once a win is found are discussed in Section 23.6.

25 The Game of Hex (cont’d)
This kind of task falls into the category of “area fill” tasks In area fill we usually agree that each inner cell has 4 neighbors. Here we have six. Here we fill the area composed of black stones with gray color.

26 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. What is recursion? Recursion is a programming technique in which a method calls itself. How is recursion implemented in a computer? By saving all temporary variables and return addresses on the system stack. What kinds of applications especially benefit from recursion? Applications that deal with nested structures or branching processes. Give an example of a task that can be programmed recursively and also, as easily, with iterations. Reverse a string; calculate n-factorial.

27 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? Give an example of a task that would be rather hard to program without recursion. Traverse a binary tree; generate all permutations of a set of objects. Give an example of a method that is too slow in a simple recursive implementation. Compute the n-th Fibonacci number What mathematical tool is very useful for understanding recursive methods and proving them correct? Mathematical induction.

28 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”? 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? 2n–1. We can prove it by math induction. Can you come up with an idea for a recursive algorithm for “area fill”? Fill the pixel, than call areaFill recursively for each neighbor of the pixel that does not yet have the desired color.


Download ppt "Java Methods Recursion Revisited Object-Oriented Programming"

Similar presentations


Ads by Google