Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of...

24
Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion Carrano: Chapter 2

Transcript of Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of...

Page 1: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

RecursionTopics:

Definition of RecursionNumeric RecursionNon-Numeric RecursionInefficiency of Recursion

Carrano: Chapter 2

Page 2: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

2CS 150

Recursion is a programming technique where a function calls itself.

Carrano - Chapter 2

What is Recursion?

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

Page 3: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

3CS 150

Recursive functions must communicate with themselves to stop the recursion.

Carrano - Chapter 2

What is Recursion?

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.

Page 4: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 4Carrano - Chapter 2

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

OperatingSystem

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”.

How Recursion Works.

Page 5: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 5Carrano - Chapter 2

A Program’s Run-Time StackProgram 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: 7yap: 10

blap: 100

void main(){ int snap = 7; int yap = 10; int blap = 100; blap = snippy(snap); yippy(yap, blap); }

snoo: 7hep: ???

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

How Recursion Works.

Page 6: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 6Carrano - Chapter 2

A Recursive Program’s Run-Time Stack

Program PDQ:

void main(){ rex(98);}void rex(int x){ if(x >= 100) return; rex(x + 1);}

How Recursion Works.

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

Page 7: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 7Carrano - Chapter 2

Recursive SolutionsFacts about a recursive solution

A recursive function calls itselfEach recursive call solves an identical, but

smaller, problemThe solution to at least one smaller problem—

the base case—is knownEventually, one of the smaller problems must be

the base case; reaching the base case enables the recursive calls to stop

Page 8: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 8Carrano - Chapter 2

Recursive SolutionsFour questions for constructing recursive

solutionsHow 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?

Page 9: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 9Carrano - Chapter 2

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 <iostream>#include <iomanip>

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;

}

Page 10: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 10Carrano - Chapter 2

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; }}

Page 11: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 11Carrano - Chapter 2

Factorial (Continued)

Page 12: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 12Carrano - Chapter 2

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: ?

Page 13: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 13Carrano - Chapter 2

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?

Page 14: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 14Carrano - Chapter 2

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 <iostream>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;}

Page 15: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 15Carrano - Chapter 2

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));}

Page 16: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

16CS 150

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 algorithmsPath Finding algorithms

Carrano - Chapter 2

Non-Numeric Recursion: Backtracking

Page 17: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

CS 150 17Carrano - Chapter 2

Non-Numeric Recursion: Flood Fill///////////////////////////////////////////////////////////////////// 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 < 0)||(row >= MAX_HEIGHT)) // too high/low

return;if((col < 0)||(col >= MAX_WIDTH)) // too left/right

return;if(canvas[row][col] == FILL_CHAR) // already filled

return;// fill current locationcanvas[row][col ] = FILL_CHAR;//make recursive function calls to check neighborspixelFiller(row-1, col, canvas); // uppixelFiller(row+1, col, canvas); // downpixelFiller(row, col-1, canvas); // leftpixelFiller(row, col+1, canvas); // right// all neighboring pixels checked, so we’re done!return;

}

Page 18: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

Carrano - Chapter 2 CS 150 18

Non-Numeric Recursion: Maze Solving///////////////////////////////////////////////////////////////////////////////// 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 <iostream>#include <fstream>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);

}

Page 19: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

Carrano - Chapter 2 CS 150 19

Maze Solving (Continued)/////////////////////////////////////////////////////////////////////////////////// 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;

}}

}

Page 20: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

Carrano - Chapter 2 CS 150 20

Maze Solving (Continued)///////////////////////////////////////////////////////////////////////////////// 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 < 0) || (currRow >= MAZE_SIDE) || (currCol < 0) || (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;

}

Page 21: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

Carrano - Chapter 2 CS 150 21

Maze Solving (Continued)/////////////////////////////////////////////////////////// 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;

Page 22: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

Carrano - Chapter 2 CS 150 22

Maze Solving (Continued)

Sample mazemaze.txt

+-+-+-+-+-+-+-+-+-+-+| | | | | |+ +-+-+ + + + +-+ + +| | | | | |+ +-+ + +-+-+-+-+ +-+| |+-+-+ +-+-+-+-+-+-+ +| | | | |+ +-+ +-+-+ + + +-+ +| | | | | |+-+ +-+-+ +-+-+ +-+-+| | | | | | |+ + + +-+-+ + + +-+ +| | | |+-+-+-+-+ +-+-+ +-+-+| | | | | |+ + +-+ +-+ + + + +-+| | | | | |+ +-+ + +-+ + +-+ + +| |S | | F| | |+-+-+-+-+-+-+-+-+-+-+

Results of running programon sample maze:

Page 23: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

Carrano - Chapter 2 CS 150 23

Recursion vs. IterationNote 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 iterativesolution cannot be found.

Page 24: Recursion Topics: Definition of Recursion Numeric Recursion Non-Numeric Recursion Inefficiency of Recursion.

Carrano - Chapter 2 CS 150 24

The Inefficiency of RecursionOne 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!