Download presentation
Presentation is loading. Please wait.
Published byJulian Kennedy Modified over 9 years ago
2
Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion
3
Recursion is a programming technique where a function calls itself. Carrano - Chapter 2 34 CS 150 void rex() { rex(); } void rex() { rex(); } void rex() { rex(); } Of course, you can’t leave it like this, or the calls won’t stop correctly
4
Recursive functions must communicate with themselves to stop the recursion. Carrano - Chapter 2 35 CS 150 void rex(int x) { if(x >= 100) return; rex(x + 1); } void rex(int x) { if(x >= 100) return; rex(x + 1); } void rex(int x) { if(x >= 100) return; rex(x + 1); } Now that we can stop the recursion, we can control how the function calls itself.
5
Carrano - Chapter 2CS 150 36 Program Memory Allocation Program B’s Run-Time Stack (Room for B’s growth) Program B’s Data Heap Program B Program A’s Run-Time Stack (Room for A’s growth) Program A’s Data Heap Program A Operating System Each program being executed on a computer is allocated extra space which it could use for its stack of function calls, and/or for “dynamically” expanding its use of memory for data. The memory used for data is known as a “heap”.
6
Carrano - Chapter 2CS 150 37 A Program’s Run-Time Stack Program XYZ: void main() { int snap = 7; int yap = 10; int blap = 100; blap = snippy(snap); yippy(yap, blap); zippy(yap); } int snippy(int snoo) { int hep = yippy(snoo,5); if (hep > 0) return hep; else return 0; } void yippy(int &yoo, int boo) { int i; for (i = 1; i < boo; i++) yoo += i; return; } snap: 7 yap: 10 blap: 100 void main() { int snap = 7; int yap = 10; int blap = 100; blap = snippy(snap); yippy(yap, blap); } snoo: 7 hep: ??? int snippy(int snoo) { int hep = yippy(snoo,5); if (hep > 0) return hep; else return 0; } yoo: boo: 5 int yippy(int &yoo, int boo) { int i; for (i = 1; i < boo; i++) yoo += i; return boo + yoo; } i: 5
7
Carrano - Chapter 2CS 150 38 A Recursive Program’s Run-Time Stack Program PDQ: void main() { rex(98); } void rex(int x) { if(x >= 100) return; rex(x + 1); } void main() { rex(98); } x = 98 void rex(int x) { if(x >= 100) return; rex(x + 1); } void rex(int x) { if(x >= 100) return; rex(x + 1); } void rex(int x) { if(x >= 100) return; rex(x + 1); } x = 100 x = 99
8
Carrano - Chapter 2CS 150 39 Facts about a recursive solution A recursive function calls itself Each recursive call solves an identical, but smaller, problem The solution to at least one smaller problem— the base case—is known Eventually, one of the smaller problems must be the base case; reaching the base case enables the recursive calls to stop
9
Carrano - Chapter 2CS 150 40 Four questions for constructing recursive solutions How can you define the problem in terms of a smaller problem of the same type? How does each recursive call diminish the size of the problem? What instance of the problem can serve as the base case? As the problem size diminishes, will you reach this base case?
10
Carrano - Chapter 2CS 150 41 Recursion Example #1: Factorial //////////////////////////////////////////////////////////////////////////// // Program file: factorial.cpp // // This program queries the user for a non-negative integer and then uses // // a recursive function to calculate the factorial of the input value. // //////////////////////////////////////////////////////////////////////////// #include using namespace std; int factorial(int n); //////////////////////////////////////////////////////////// // The main function asks the user for a value, calls the // // recursive factorial function, and outputs the result. // //////////////////////////////////////////////////////////// void main() { int number, result; cout << "Enter a non-negative integer for factorial computation: "; cin >> number; while (number < 0) { cout << "I said, enter a NON-NEGATIVE integer: "; cin >> number; } cout << endl; result = factorial(number); cout << "FINAL RESULT: " << number << "! = " << result << endl << endl; }
11
Carrano - Chapter 2CS 150 42 Factorial (Continued) ///////////////////////////////////////////////////////////////////////////// // Function factorial recursively calculates the factorial of parameter n, // // outputting entering and exiting messages to demonstrate to the user the // // recursive function calls which make the final calculation possible. // ///////////////////////////////////////////////////////////////////////////// int factorial(int n) { static int indent = 0; int result; cout << setw(indent) << "" << "ENTERING FACTORIAL ROUTINE WITH N = ” << n << endl << endl; if ((n == 1) || (n == 0)) { cout << setw(indent) << "" << "EXITING FACTORIAL ROUTINE WITH N = " << n << ", " << n << "! = " << 1 << endl << endl; indent -= 4; return 1; } else { indent += 4; result = n * factorial(n - 1); cout << setw(indent) << "" << "EXITING FACTORIAL ROUTINE WITH N = " << n << ", " << n << "! = " << result << endl << endl; indent -= 4; return result; }
12
Carrano - Chapter 2CS 150 43 Factorial (Continued)
13
Carrano - Chapter 2CS 150 44 Tracing Through Factorial’s Run-Time Stack number: 5 void main() { : result = factorial(number); : } n: 5 result: 5*? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } n: 4 result: 4*? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } n: 3 result: 3*? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } n: 2 result: 2*? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } n: 1 result: ? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else : } result: ?
14
Carrano - Chapter 2CS 150 45 Recursion Example #2: Combination Given n objects, how many different sets of size k can be selected? This problem can be solved by solving two slightly smaller problems and summing the results (sounds pretty recursive!): Problem 1: Assuming that the first object is selected, how many size k-1 sets can be selected from the remaining n-1 objects? Problem 2: Assuming that the first object is not selected, how many size k sets can be selected from the remaining n-1 objects?
15
Carrano - Chapter 2CS 150 46 Combination (Continued) ///////////////////////////////////////////////////////////////////// // Program file: combination.cpp // // This program queries the user for a set size and a subset size, // // and then recursively computes the number of different subsets // // of the appropriate size that could be selected from the set. // ///////////////////////////////////////////////////////////////////// #include using namespace std; int computeCombo(int setSize, int subsetSize); // Main asks the user for the set & subset sizes, calls the // // function producing the combination, and outputs the result. // void main() { int sizeOfCollection; int sizeOfSelection; cout << "How many objects in the master collection? "; cin >> sizeOfCollection; cout << "How many objects in a single selection? "; cin >> sizeOfSelection; cout << endl << endl; cout << "FOR " << sizeOfCollection << " FANCY OBJECTS COLLECTED" << endl << "AND " << sizeOfSelection << " LUCKY CHOICES SELECTED," << endl << "THERE\'S " << computeCombo(sizeOfCollection, sizeOfSelection) << " DIFFERENT SUBSETS" << endl << "BUT EACH HAS " << sizeOfCollection-sizeOfSelection << " ANGRY UPSETS" << endl << "\'CAUSE THE REST OF THE SAPS ARE REJECTED!" << endl << endl; }
16
Carrano - Chapter 2CS 150 47 Combination (Continued) ///////////////////////////////////////////////////////////// // Function computeCombo recursively calculates the number // // of different combinations of size subsetSize that can // // be obtained from a collection of size setSize. // ///////////////////////////////////////////////////////////// int computeCombo(int setSize, int subsetSize) { if (subsetSize > setSize) return 0; if (subsetSize == setSize)) return 1; if (subsetSize == 1)) return setSize; return (computeCombo(setSize-1, subsetSize-1) + computeCombo(setSize-1, subsetSize)); }
17
Recursion allows the use of a technique called “Backtracking” where attempts at a solution are made by trying one of several possibilities and, when a ‘dead end’ is reached, the attempts backtrack to a former decision point and try another possibility. Examples include: Flood Filling algorithms Path Finding algorithms Carrano - Chapter 2 48 CS 150
18
Carrano - Chapter 2CS 150 49 /////////////////////////////////////////////////////////////////// // This function uses recursion to fill an area of a character // // grid by filling each non-filled point and then checking that // // point’s neighbors. // ////////////////////////////////////////////////////////////////// void pixelFiller(int row, int col, char canvas[MAX_HEIGHT][MAX_WIDTH]) { //check the base cases for point canvas[row][col] if((row = MAX_HEIGHT)) // too high/low return; if((col = MAX_WIDTH)) // too left/right return; if(canvas[row][col] == FILL_CHAR) // already filled return; // fill current location canvas[row][col ] = FILL_CHAR; //make recursive function calls to check neighbors pixelFiller(row-1, col, canvas); // up pixelFiller(row+1, col, canvas);// down pixelFiller(row, col-1, canvas);// left pixelFiller(row, col+1, canvas);// right // all neighboring pixels checked, so we’re done! return; }
19
Carrano - Chapter 2CS 150 50 /////////////////////////////////////////////////////////////////////////////// // This program uses recursion to traverse a maze in the form of a character // // grid, finding the path through the maze, and marking it. // /////////////////////////////////////////////////////////////////////////////// #include using namespace std; const int MAZE_SIDE = 21; const char START_CHAR = 'S'; const char FINISH_CHAR = 'F'; const char BLANK_CHAR = ' '; const char PATH_CHAR = 'o'; void getMaze(char matrix[MAZE_SIDE][MAZE_SIDE], int &startRow, int &startCol, int &destRow, int &destCol); bool solveMaze(char matrix[MAZE_SIDE][MAZE_SIDE], int currRow, int currCol, int destRow, int destCol); void printMaze(char matrix[MAZE_SIDE][MAZE_SIDE]); // Function main retrieves, solves, outputs the maze. // void main() { char maze[MAZE_SIDE][MAZE_SIDE]; int startRow, startCol; int destRow, destCol; getMaze(maze, startRow, startCol, destRow, destCol); solveMaze(maze, startRow, startCol, destRow, destCol); printMaze(maze); }
20
Carrano - Chapter 2CS 150 51 ///////////////////////////////////////////////////////////////////////////////// // Function getMaze retrieves the maze from a specific input file, assuming // // that it is size MAZE_SIDE x MAZE_SIDE, and that it is stored as MAZE_SIDE // // lines of MAZE_SIDE characters. The four function parameters will be // // assigned the row and column numbers of the start and finish of the maze. // ///////////////////////////////////////////////////////////////////////////////// void getMaze(char matrix[MAZE_SIDE][MAZE_SIDE], int &startRow, int &startCol, int &destRow, int &destCol) { ifstream sourceFile; char nextChar; sourceFile.open("maze.txt"); for (int i = 0; i < MAZE_SIDE; i++) for (int j = 0; j < MAZE_SIDE; j++) { sourceFile.get(nextChar); while(nextChar == '\n') sourceFile.get(nextChar); matrix[i][j] = nextChar; if(nextChar == START_CHAR) { startRow = i; startCol = j; } else if(nextChar == FINISH_CHAR) { destRow = i; destCol = j; }
21
Carrano - Chapter 2CS 150 52 /////////////////////////////////////////////////////////////////////////////// // Function solveMaze will recursively find and mark a path through the maze.// //////////////////////////////////////////////////////////////////////////////// bool solveMaze(char maze[MAZE_SIDE][MAZE_SIDE], int currRow, int currCol, int destRow, int destCol) { //system("cls"); printMatrix(maze); if((currRow = MAZE_SIDE) || (currCol = MAZE_SIDE)) return false; if(maze[currRow][currCol] == FINISH_CHAR) return true; if((maze[currRow][currCol] != BLANK_CHAR) && (maze[currRow][currCol] != START_CHAR)) return false; if(maze[currRow][currCol] != START_CHAR) maze[currRow][currCol] = PATH_CHAR; if(solveMaze(maze, currRow-1, currCol, destRow, destCol)) return true; else if(solveMaze(maze, currRow+1, currCol, destRow, destCol)) return true; else if(solveMaze(maze, currRow, currCol-1, destRow, destCol)) return true; else if(solveMaze(maze, currRow, currCol+1, destRow, destCol)) return true; if(maze[currRow][currCol] != START_CHAR) maze[currRow][currCol] = BLANK_CHAR; return false; }
22
Carrano - Chapter 2CS 150 53 ///////////////////////////////////////////////////////// // Function printMaze outputs the entire maze grid. // ///////////////////////////////////////////////////////// void printMaze(char maze[MAZE_SIDE][MAZE_SIDE]) { for (int row = 0; row < MAZE_SIDE; row++) { for (int col = 0; col < MAZE_SIDE; col++) cout << maze[row][col]; cout << endl; } cout << endl; return;
23
Carrano - Chapter 2CS 150 54 Sample maze maze.txt +-+-+-+-+-+-+-+-+-+-+ | | | + +-+-+ + + + +-+ + + | | | + +-+ + +-+-+-+-+ +-+ | +-+-+ +-+-+-+-+-+-+ + | | | | | + +-+ +-+-+ + + +-+ + | | | +-+ +-+-+ +-+-+ +-+-+ | | | | | | | + + + +-+-+ + + +-+ + | | +-+-+-+-+ +-+-+ +-+-+ | | | + + +-+ +-+ + + + +-+ | | | + +-+ + +-+ + +-+ + + | |S | | F| | | +-+-+-+-+-+-+-+-+-+-+ Results of running program on sample maze:
24
Carrano - Chapter 2CS 150 55 Note that many problems that can be solved recursively can just as easily be solved via iteration (i.e., looping). In fact, the use of recursion when an iterative solution can be found is rather wasteful, forcing the operating system to do extra work and taking the risk that a stack overflow will occur. When To Use Recursion Instead Of Iteration When a straightforward iterative solution cannot be found.
25
Carrano - Chapter 2CS 150 56 One of the big drawbacks to using recursion is the inherent inefficiency of many recursive algorithms. For instance, our maze solving routine frequently revisits coordinates that have already been seen and eliminated as possible steps in the path! On the other hand, some recursive algorithms are vast improvements over alternative solutions and are implemented with very simple code. How To Measure The Efficiency Of A Recursive Algorithm Study Math 224 real hard, and take CS 240 and 340!
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.