Recursion Recursion is a fundamental programming technique that can provide an elegant solution certain kinds of problems We will focus on: thinking in.

Slides:



Advertisements
Similar presentations
Chapter 17 Recursion.
Advertisements

© 2010 Pearson Addison-Wesley. All rights reserved. Addison Wesley is an imprint of CHAPTER 7: Recursion Java Software Structures: Designing and Using.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Java Software Solutions Foundations of Program Design Sixth Edition by Lewis.
© Janice Regan, CMPT 102, Sept CMPT 102 Introduction to Scientific Computer Programming Recursion.
Slides prepared by Rose Williams, Binghamton University Chapter 11 Recursion.
1 Recursion  Recursion is a fundamental programming technique that can provide an elegant solution certain kinds of problems  Chapter 11 of the book.
Recursion. Objectives At the conclusion of this lesson, students should be able to Explain what recursion is Design and write functions that use recursion.
Chapter 10 Recursion. Copyright © 2005 Pearson Addison-Wesley. All rights reserved Chapter Objectives Explain the underlying concepts of recursion.
Copyright © 2003 Pearson Education, Inc. Slide 1.
ELC 310 Day 24. © 2004 Pearson Addison-Wesley. All rights reserved11-2 Agenda Questions? Problem set 5 Parts A Corrected  Good results Problem set 5.
CHAPTER 10 Recursion. 2 Recursive Thinking Recursion is a programming technique in which a method can call itself to solve a problem A recursive definition.
Chapter 11 Recursion. © 2004 Pearson Addison-Wesley. All rights reserved11-2 Recursion Recursion is a fundamental programming technique that can provide.
© 2004 Pearson Addison-Wesley. All rights reserved October 27, 2006 Recursion (part 2) ComS 207: Programming I (in Java) Iowa State University, FALL 2006.
Chapter 7 Arrays. © 2004 Pearson Addison-Wesley. All rights reserved11-2 Arrays Arrays are objects that help us organize large amounts of information.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Java Software Solutions Foundations of Program Design Sixth Edition by Lewis.
Instructor: Alexander Stoytchev CprE 185: Intro to Problem Solving (using C)
Chapter 8 Recursion Modified.
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
Chapter 4 Recursion. Copyright © 2004 Pearson Addison-Wesley. All rights reserved.1-2 Chapter Objectives Explain the underlying concepts of recursion.
CSIS 123A Lecture 9 Recursion Glenn Stevenson CSIS 113A MSJC.
1Recursion  Recursion is a fundamental programming technique that can provide an elegant solution certain kinds of problems  We will focus on: thinking.
CSE 501N Fall ‘09 12: Recursion and Recursive Algorithms 8 October 2009 Nick Leidenfrost.
11-1 Recursive Thinking A recursive definition is one which uses the word or concept being defined in the definition itself When defining an English word,
Lecture 7 b Recursion is a fundamental programming technique that can provide an elegant solution to certain kinds of problems b Today: thinking in a recursive.
Instructor: Alexander Stoytchev CprE 185: Intro to Problem Solving (using C)
© 2011 Pearson Education, publishing as Addison-Wesley Chapter 8: Recursion Presentation slides for Java Software Solutions for AP* Computer Science 3rd.
1 Recursion Recursion is a powerful programming technique that provides elegant solutions to certain problems. Chapter 11 focuses on explaining the underlying.
© Janice Regan, CMPT 128, February CMPT 128: Introduction to Computing Science for Engineering Students Recursion.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 12 Recursion.
Recursion Chapter 17 Instructor: Scott Kristjanson CMPT 125/125 SFU Burnaby, Fall 2013.
Recursion. Objectives At the conclusion of this lesson, students should be able to Explain what recursion is Design and write functions that use recursion.
Function Recursion to understand recursion you must understand recursion.
COS 312 DAY 24 Tony Gauvin. Ch 1 -2 Agenda Questions? Assignment 6 Corrected Assignment 7 (bonus) – Due May 11 – Will be scored on 15 point scale, points.
Recursion.
Chapter 13 Recursion Copyright © 2016 Pearson, Inc. All rights reserved.
Recursion Version 1.0.
to understand recursion you must understand recursion
CHAPTER 4: Linked Structures
Recursion -- Introduction
CprE 185: Intro to Problem Solving (using C)
Abdulmotaleb El Saddik University of Ottawa
Recursive Thinking Chapter 9 introduces the technique of recursive programming. As you have seen, recursive programming involves spotting smaller occurrences.
Chapter 8: Recursion Java Software Solutions
Java Software Structures: John Lewis & Joseph Chase
Chapter 14 Recursion. Chapter 14 Recursion Overview 14.1 Recursive Functions for Tasks 14.2 Recursive Functions for Values 14.3 Thinking Recursively.
to understand recursion you must understand recursion
Recursive Thinking Chapter 9 introduces the technique of recursive programming. As you have seen, recursive programming involves spotting smaller occurrences.
Recursion "To understand recursion, one must first understand recursion." -Stephen Hawking.
Recursive Definitions
Chapter 12 Recursion (methods calling themselves)
Recursion (part 2) October 26, 2007 ComS 207: Programming I (in Java)
Java Software Solutions Foundations of Program Design Seventh Edition
Chapter 8: Recursion Java Software Solutions
Chapter 8 Recursion.
Recursion (part 1) October 24, 2007 ComS 207: Programming I (in Java)
Basics of Recursion Programming with Recursion
Chapter 11 Recursion.
Chapter 8: Recursion Java Software Solutions
11 Recursion Software Solutions Lewis & Loftus java 5TH EDITION
Recursion (part 2) March 22, 2006 ComS 207: Programming I (in Java)
Chapter 13 Recursion Copyright © 2010 Pearson Addison-Wesley. All rights reserved.
Java Software Solutions Foundations of Program Design Sixth Edition
Module 4 Loops and Repetition 9/19/2019 CSE 1321 Module 4.
Presentation transcript:

Recursion Recursion is a fundamental programming technique that can provide an elegant solution certain kinds of problems We will focus on: thinking in a recursive manner programming in a recursive manner the correct use of recursion recursion examples

Recursive Thinking 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 is often 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

Recursive Thinking We have used methods that call other methods to help them solve a problem. Sometimes methods need to call themselves again. A recursive definition is one which uses the word or concept being defined in the definition itself.

Recursion But in other situations, a recursive definition can be an appropriate way to express a concept. Let’s look at a presentation which illustrates such thinking.

Recursive Definitions Consider the following list of numbers: 24, 88, 40, 37 Such a list can be defined as 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

Recursive Definitions The recursive part of the LIST definition is used several times, terminating with the non-recursive part: number comma LIST 24 , 88, 40, 37 88 , 40, 37 40 , 37 number 37

Infinite Recursion All recursive definitions have to have a non-recursive part If they didn't, there would be no way to terminate the recursive path Such a definition would cause infinite recursion This problem is similar to an infinite loop, except that the loop is endlessly calling itself..

Recursion The non-recursive part is often called the base case. The algorithm must ensure that the base case is reached. Recursion is based on two key problem-solving concepts: divide and conquer and self-similarity. We repeatedly break down a big problem into a sequence of smaller and smaller problems until we arrive at the trivial case.

Recursion Look at the task of printing hello 5 times. It involves printing hello N-1 times. Solving this task involves the similar task of printing hello N-2 times etc.

Recursion /* prints each character of s – e.g “hello” public void printString(String s) { if(s.length() == 1 ) return else{ System.out.print(s.charAt(0)); printString(s.substring(1)); // takes off the first character of the word } Prints out the first charaction of “hello”, then “ello”, then “llo” then “lo” then “o”

Recursive Definitions 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 Eventually, the base case of 1! is reached

Recursive Definitions 5! 5 * 4! 4 * 3! 3 * 2! 2 * 1! 1 1 = BASE CASE 2 6 24 120

Recursive Programming When a method calls itself, 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 local variables As always, when the method ends, execution returns to the method that invoked it (which is an earlier invocation of itself)

Recursion The following method solves the summation of the numbers from 1 and any positive integer N. 1. public int sum(int N) { 2. int result; 3. if(N ==1) 4. result = 1; 5. else result = N + Sum (N-1); 6. return result; } This method embodies our recursive definition that the sum of the numbers between 1 and N = N + the sum of the numbers between 1 and N-1.

Recursive Programming main sum sum(3) sum(1) sum(2) result = 1 result = 3 result = 6

Recursion If we pass an initial value of 2 to the sum method: Since N is not equal to 1, the method sum is called again with an argument of N-1 or 1. This is a new call to the method sum, with a new parameter N and a new local variable result. This call and its environment is stored on the stack Since N is now equal to 1, the result of 1 is returned without any further recursive calls. Control returns to the first version of sum. The return value of 1 is added to the initial value of N in that call to sum which is 2. Therefore result is assigned the value 3 which is returned to the main method.

Recursion The base case is when N equals 1. At this point no further calls are made to the sum method. The recursion begin to unwinds into the earlier version of the sum method, returning a value each time. Each return value contributes to the summation of the sum at a higher level. Without the base case, infinite recursion would result. Each call also requires more memory space so that infinite recursion results in a run-time error indicating that memory has been exhausted.

Recursion The call to sum is recursive because it is calling itself. The parameter to sum is decremented each time sum is called, until it reaches the base case of 1. If the method is called with a value of 1, which is stored in N,, the result 1 is returned to main. MAIN result = 2 MAIN sum(2) sum(1) result = 1 SUM SUM result = 1 SUM

Recursive Programming Note that just because we can use recursion to solve a problem, that does not mean this is the optimal solution. 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 and requires less memory if N is a large number.

Recursion The iterative solution is easier to understand: sum = 0; for(int number = 1; number <=N; number++) sum += number; Recursion has memory overhead. However, for some problems, recursion provides an elegant solution, often cleaner than an iterative version

1. Print all the digits but the last one stacked vertically Example To write a method that stacks non-negative numbers to the screen vertically such as 1234 : 1 2 3 4 We might break the problem into two parts: 1. Print all the digits but the last one stacked vertically 2. Print the last one.

An example if the number has only one digit { write that digit } To print the actual number we would divide the number by 10 to get the first three digits and use the mod operator to get the last digit. The pseudocode is: if the number has only one digit { write that digit } else { Write the digits of number/10 vertically write the single digit of number % 10

The WriteVertical method public static void writeVertical(int number) { if (number < 10) System.out.println(number); // Write the one digit. else { writeVertical(number/10); // Write all but the last digit. System.out.println(number % 10); // Write the last digit. }

writeVertical The base case here is simple - when number has only 1 digit. The recursive call occurs where: writeVertical(number/10); // Write all but the last digit System.out.println(number % 10); // Write the last digit. What actually happens with writeVertical(3) The argument 3 is copied the method’s parameter - number which provides it with an initial value.

writeVertical Since the number is less than 10, it writes the number. With an argument greater than 10 like 37, it would go to the statements in the else part of the code. else { writeVertical(number/10); // Write all but the last digit. System.out.println(number % 10); // Write the last digit. } Since 37/10 is 3 this is an activation of the previous problem of writeVertical(3) which prints out 3 on a single line. After the 3 is printed, we go to the next line which prints out the last digit which is 7 % 10.

Recursion When a method - e.g. method 1 -is activated, the computer stores information about the method before activating it. It stores method 1’s parameters and local variables and information that will allow it to return to place in the code where the method call occurs. Then it starts the actual method. This is called the Activation Record of a Stack Frame.

Recursion If another method - method 2 - is called from within method 1, method 1’s execution is temporarily stopped and the same information is stored for method 2. It stores where the call for the second method occurred in the first method. It will continue to this for every recursive method call.

Recursion An Activation Record is kept for all methods. Activation Record for WriteVertical number: 36 When the method returns, the computation should begin at line where execution stopped

Executing superWriteVertical Using the number 36 it enters the method. The number is not less than 10 so it makes a recursive call to WriteVertical which has its own Activation Record. The Activation Records are stored in a stack called the Execution Stack Activation Record First call number: 36 When the method returns, the computation should begin at SPOT 1 of the program.

TRACING EXECUTION Activation Record for first call to WriteVertical number: 36 When the method returns, the computation should begin at SPOT 1 of the program. Activation Record for second call to WriteVertical number: 3 Method finishes and returns

Tracing Execution WriteVertical(36) which makes a call to Eventually in all recursive functions there must be a stopping case or else there is an infinite sequence of recursive calls

Using Recursion Recursion is best served when it is easy to define a smaller subset of the problem in terms of the original. Consider the task of repeatedly displaying a set of images in a mosaic that is reminiscent of looking in two mirrors reflecting each other. The base case is reached when the area for the images shrinks to a certain size. In Repeating_Pictures.java, the applet displays several pictures.. There are actually only 3 distinct pictures among all the ones shown.

Using Recursion Recursion is best served when it is easy to define a smaller subset of the problem in terms of the original. Consider the task of repeatedly displaying a set of images in a mosaic that is reminiscent of looking in two mirrors reflecting each other. The base case is reached when the area for the images shrinks to a certain size. See MirroredPictures.java (page 483)

Recursion The entire area is divided into 4 quadrants, separated by lines. A picture of the world(with a circle indicating the Himalayan mountain section) is in the top-right quadrant. The bottom-left quadrant contain a picture of Mt. Everest. In the bottom-right quadrant is a picture of a mountain goat.

Tiled Pictures

Repeating Pictures In the top left quadrant contains a copy of the entire collage, including itself. In this smaller version you can see the three simple pictures in their three quadrants. And again, in the upper-left corner the picture is repeated (including itself). It has the same effect as when you look at a mirror in the reflection of another mirror. This repetition continues for several levels.

Mirrored_Images This effect is created easily using recursion. In the applet, the paint method invokes another method called draw pictures. The draw_pictures method accepts a parameter that defines the size of the area in which pictures are displayed. It draws the three standard images using drawImage. The draw_pictures method draws the upper left quadrant recursively.

public class TiledPictures extends JApplet { private final int APPLET_WIDTH = 320; private final int APPLET_HEIGHT = 320; private final int MIN = 20; // smallest picture size private Image world, everest, goat; //----------------------------------------------------------------- // Loads the images. //----------------------------------------------------------------- public void init() { world = getImage (getDocumentBase(), "world.gif"); everest = getImage (getDocumentBase(), "everest.gif"); goat = getImage (getDocumentBase(), "goat.gif"); setSize (APPLET_WIDTH, APPLET_HEIGHT); }

//----------------------------------------------------------------- // Performs the initial call to the drawPictures method. //----------------------------------------------------------------- public void paint (Graphics page) { drawPictures (APPLET_WIDTH, page); } }

//----------------------------------------------------------------- // Draws the three images, then calls itself recursively. //----------------------------------------------------------------- public void drawPictures (int size, Graphics page) { page.drawImage (everest, 0, size/2, size/2, size/2, this); page.drawImage (goat, size/2, 0, size/2, size/2, this); page.drawImage (world, size/2, size/2, size/2, size/2, this); if (size > MIN) drawPictures (size/2, page); }

Mirrored_Images On each invocation, if the drawing area is large enough the draw_pictures method is invoked again, using a smaller drawing area. Eventually the drawing area becomes so small that the recursive call is not performed. Each time the draw-pictures method is invoked, the size passed as a parameter is used to determine the area in which the pictures are presented Draw_ pictures applet relative to the co-ordinates <0,0>

Drawing Mirrors The two lines defining the four quadrants are drawn relative to the size of the current draw area. The drawImage method automatically scales the pictures to fit in the area indicated. The base case of the recursion in this problem specifies a minimum size for the drawing area. Because the size is decreased each time, eventually the base case is reached and the recursion stops. That is why the last upper left corner is empty in the smallest version of the collage.

Maze Traversal We can use recursion to find a path through a maze From each location, we can search in each direction Recursion keeps track of the path through the maze The base case is an invalid move or reaching the final destination See MazeSearch.java (page 472) See Maze.java (page 474)

Using Recursion A maze is solved by trial and error -- choosing a direction, following a path, returning to a previous point if the wrong move is made. As such, it is another good candidate for a recursive solution. The base case is an invalid move or one which reaches the final destination. In Maze_Search.java, a 2-D array of integers filled with 0’s and 1’s. A ‘1’ indicates a clear path and a ‘0’ a blocked path. As the maze is solved these parameters are changed to other values to indicate attempted and successful paths through the maze.

// Class Maze represents a maze of characters. The goal is to get // from the top left corner to the bottom right, following a path // of 1's. class Maze {   int[][] grid = {{1,1,1,0,1,1,0,0,0,1,1,1,1}, {1,0,1,1,1,0,1,1,1,1,0,0,1}, {0,0,0,0,1,0,1,0,1,0,1,0,0}, {1,1,1,0,1,1,1,0,1,0,1,1,1}, {1,0,1,0,0,0,0,1,1,1,0,0,1}, {1,0,1,1,1,1,1,1,0,1,1,1,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,1,1,1,1,1,1} };

Recursion - Maze The only valid moves are right, left, up and down with no diagonal moves allowed. The goal is to start in the upper-left corner of the maze (0,0) and find a path that reaches the bottom-right corner. The Maze_Search class contain the main method which instantiates the maze and prints out it as a matrix, solves the maze if possible and prints out solved version of the maze. The recursive method traverse returns a boolean value that indicates whether a solution was found. First the method determines if a move to that row and column is valid.

Recursion A move is considered valid if: 1. It stays within the grid 2. if the grid contains a ‘1’ in that cell The initial call to traverse passes in the upper-left location(0,0). If the move is valid, the grid entry is changed from a 1 to a 3 marking this location as visited so that later we don’t retrace out steps.

//====================================== // Determines if a specific location is valid. //=========================================== private boolean valid (int row, int column) {   boolean result = false; // check if cell is in the bounds of the matrix if (row >= 0 && row < grid.length && column >= 0 && column < grid[0].length) // check if cell is not blocked and not previously tried if (grid[row][column] == 1) result = true; return result; } // method valid

//====================================== // Determines if a specific location is valid. //=========================================== private boolean valid (int row, int column) {   boolean result = false; // check if cell is in the bounds of the matrix if (row >= 0 && row < grid.length && column >= 0 && column < grid[0].length) // check if cell is not blocked and not previously tried if (grid[row][column] == 1) result = true; return result; } // method valid

The 3 possibilities for the base case for each recursive call are: Then the traverse method determines if the maze has been completed by having reached the bottom right location of the maze. The 3 possibilities for the base case for each recursive call are: 1. an invalid move because it is out of bounds 2. an invalid move because it has been tried before(it contains a 3) so we go back to a previous cell 3. a move that arrives at the final location – Success!

// Recursively traverse the maze // Recursively traverse the maze. and inserts special characters indicating locations that have been tried and that eventually become part of the solution. public boolean traverse (int row, int column) {   oolean done = false; if (valid (row, column)) // calls method to determine the cell holds a 1 {   grid[row][column] = 3; // marks cell as tried and sets it to 3   if (row == grid.length-1 && column == grid[0].length-1) done = true; // maze is solved ,we have reached the end else { done = traverse (row+1, column); // move down as far as possible if (!done) // if that did not work, done = traverse (row, column+1); // move right if (!done) // if that did not work, done = traverse (row-1, column); // move up done = traverse (row, column-1); // move left } if (done) // part of the final path - this is marked when the calls unwind grid[row][column] = 7; // this marks the path to the final solution } // closes if valid return done; } // method traverse

Mazes If the current location is not the bottom-right corner , we search for a solution in each of the primary directions, if necessary. Down, Right Up and Left First, we look down by recursively calling the traverse method and passing in the new location The logic of the solve methods starts all over again using this new position.

Mazes A solution is found by either starting down from the current location or it is not found. If it’s not found, we try moving right, then up. Finally if no direction yields a correct path we try left. If no direction from this location yields a correct solution, then there is not path from this location and the traverse method returns false.

Maze_Search If a solution was found from the current location, the grid entry is changed to a 7. These are marked when the method calls unwind. Therefore, when the final maze is printed: The locations left on the stack are part of the solution. the zeros still indicate a blocked path and A 1 indicates an open path that was never tried A 3 indicates a path that was tried but failed to yield a correct solution 4. A 7 indicates a part of the final solution of the maze

Maze_Search Maze_Search Solution moves are down right up and left   7770110001111 3077707771001 0000707070300 7770777070333 7070000773003 7077777703333 7000000000000 7777777777777