| Presentation slides for | |
| Java Software Solutions | |
| Foundations of Program Design | |
| Third Edition | |
| by John Lewis and William Loftus | |
| Java Software Solutions is published by Addison-Wesley | |
| Presentation slides are copyright 2002 by John Lewis and William Loftus. All rights reserved. | |
| Instructors using the textbook may use and modify these slides for pedagogical purposes. | |
| Recursion is a fundamental programming technique that can provide elegant solutions certain kinds of problems | ||
| Chapter 11 focuses on: | ||
| thinking in a recursive manner | ||
| programming in a recursive manner | ||
| the correct use of recursion | ||
| examples using recursion | ||
| recursion in graphics | ||
| Recursion is a programming technique in which a method can call itself to solve a problem | |||||
| A recursive definition is one which uses the word or concept being defined in the definition itself; when defining an English word, a recursive definition usually is not helpful | |||||
| But in other situations, a recursive definition can be an appropriate way to express a concept | |||||
| Before applying recursion to programming, it is best to practice thinking recursively | |||||
| Consider the following list of numbers: | |||||
| 24, 88, 40, 37 | |||||
| A list can be defined recursively | |||||
| A LIST is a: number | |||||
| or a: number comma LIST | |||||
| That is, a LIST is defined to be a single number, or a number followed by a comma followed by a LIST | |||||
| The concept of a LIST is used to define itself | |||||
| The recursive part of the LIST definition is used several times, ultimately terminating with the non-recursive part: | |||||
| number comma LIST | |||||
| 24 , 88, 40, 37 | |||||
| number comma LIST | |||||
| 88 , 40, 37 | |||||
| number comma LIST | |||||
| 40 , 37 | |||||
| number | |||||
| 37 | |||||
| All recursive definitions must have a non-recursive part | |||||
| If they don't, there is no way to terminate the recursive path | |||||
| A definition without a non-recursive part causes infinite recursion | |||||
| This problem is similar to an infinite loop with the definition itself causing the infinite “loop” | |||||
| The non-recursive part often is called the base case | |||||
| Mathematical formulas often are expressed recursively | |||||
| N!, for any positive integer N, is defined to be the product of all integers between 1 and N inclusive | |||||
| This definition can be expressed recursively as: | |||||
| 1! = 1 | |||||
| N! = N * (N-1)! | |||||
| The concept of the factorial is defined in terms of another factorial until the base case of 1! is reached | |||||
| 5! | |||||
| 5 * 4! | |||||
| 4 * 3! | |||||
| 3 * 2! | |||||
| 2 * 1! | |||||
| 1 | |||||
| A method in Java can invoke itself; if set up that way, it is called a recursive method | |||||
| The code of a recursive method must be structured to handle both the base case and the recursive case | |||||
| Each call to the method sets up a new execution environment, with new parameters and new local variables | |||||
| As always, when the method execution completes, control returns to the method that invoked it (which may be an earlier invocation of itself) | |||||
| Consider the problem of computing the sum of all the numbers between 1 and any positive integer N, inclusive | |
| This problem can be expressed recursively as: | |
| public int sum (int num) | |
| { | |
| int result; | |
| if (num == 1) | |
| result = 1; | |
| else | |
| result = num + sum (num - 1); | |
| return result; | |
| } |
| Just because we can use recursion to solve a problem, doesn't mean we should | |||||
| For instance, we usually would not use recursion to solve the sum of 1 to N problem, because the iterative version is easier to understand; in fact, there is a formula which is superior to both recursion and iteration! | |||||
| You must be able to determine when recursion is the correct technique to use | |||||
| Every recursive solution has a corresponding iterative solution | |
| For example, the sum (or the product) of the numbers between 1 and any positive integer N can be calculated with a for loop | |
| Recursion has the overhead of multiple method invocations | |
| Nevertheless, recursive solutions often are more simple and elegant than iterative solutions |
| A method invoking itself is considered to be direct recursion | |||||
| A method could invoke another method, which invokes another, etc., until eventually the original method is invoked again | |||||
| For example, method m1 could invoke m2, which invokes m3, which in turn invokes m1 again until a base case is reached | |||||
| This is called indirect recursion, and requires all the same care as direct recursion | |||||
| It is often more difficult to trace and debug | |||||
| We can use recursion to find a path through a maze; a path can be found from any location if a path can be found from any of the location’s neighboring locations | |||||
| At each location we encounter, we mark the location as “visited” and we attempt to find a path from that location’s “unvisited” neighbors | |||||
| Recursion keeps track of the path through the maze | |||||
| The base cases are an prohibited move or arrival at the final destination | |||||
| See MazeSearch.java (page xxx) | |
| See Maze.java (page xxx) | |
| The Towers of Hanoi is a puzzle made up of three vertical pegs and several disks that slide on the pegs | |||||
| The disks are of varying size, initially placed on one peg with the largest disk on the bottom with increasingly smaller disks on top | |||||
| The goal is to move all of the disks from one peg to another according to the following rules: | |||||
| We can move only one disk at a time | |||||
| We cannot place a larger disk on top of a smaller disk | |||||
| All disks must be on some peg except for the disk in transit between pegs | |||||
| (Figure 11.5 here) |
| A solution to the three-disk Towers of Hanoi puzzle | |
| (Figure 11.6 here) |
| To move a stack of N disks from the original peg to the destination peg | ||
| move the topmost N - 1 disks from the original peg to the extra peg | ||
| move the largest disk from the original peg to the destination peg | ||
| move the N-1 disks from the extra peg to the destination peg | ||
| The base case occurs when a “stack” consists of only one disk | ||
| This recursive solution is simple and elegant even though the number of move increases exponentially as the number of disks increases | ||
| The iterative solution to the Towers of Hanoi is much more complex | ||
| See SolveTowers.java (page xxx) | |
| See TowersOfHanoi.java (page xxx) | |
| Consider the task of repeatedly displaying a set of tiled images in a mosaic in which one of the tiles contains a copy of the entire collage | |||||
| The base case is reached when the area for the “remaining” tile shrinks to a certain size | |||||
| See TiledPictures.java (page xxx) | |||||
| A fractal is a geometric shape than can consist of the same pattern repeated in different scales and orientations | |||||
| The Koch Snowflake is a particular fractal that begins with an equilateral triangle | |||||
| To get a higher order of the fractal, the middle of each edge is replaced with two angled line segments | |||||
| (Figure 11.7 here) | |
| See KochSnowflake.java (page xxx) | |
| See KochPanel.java (page xxx) |
| Chapter 11 has focused on: | ||
| thinking in a recursive manner | ||
| programming in a recursive manner | ||
| the correct use of recursion | ||
| examples using recursion | ||
| recursion in graphics | ||