Chapter 5 Recursion

16
CS 240 CS 240 Chapter 5 - Recursion Chapter 5 - Recursion Page Page 1 Chapter 5 Chapter 5 Recursion Recursion Recursion can be a very effective technique for solving Recursion can be a very effective technique for solving what would otherwise be extremely elaborate what would otherwise be extremely elaborate problems. problems. Sample recursive applications include: Sample recursive applications include: Backtracking algorithms. Backtracking algorithms. Programming language definition. Programming language definition. Matrix operations. Matrix operations. In addition, a solid understanding of recursion is In addition, a solid understanding of recursion is helpful in analyzing the time complexity of algorithms. helpful in analyzing the time complexity of algorithms. Mathematical induction. Mathematical induction. Recurrence relations. Recurrence relations. Recursion-related analysis techniques include: Recursion-related analysis techniques include:

description

Chapter 5 Recursion. Recursion can be a very effective technique for solving what would otherwise be extremely elaborate problems. Sample recursive applications include:. Backtracking algorithms. Programming language definition. Matrix operations. - PowerPoint PPT Presentation

Transcript of Chapter 5 Recursion

Page 1: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 11

Chapter 5Chapter 5RecursionRecursion

Recursion can be a very effective technique Recursion can be a very effective technique for solving what would otherwise be extremely for solving what would otherwise be extremely elaborate problems.elaborate problems.

Sample recursive applications include:Sample recursive applications include: Backtracking algorithms.Backtracking algorithms. Programming language definition.Programming language definition. Matrix operations.Matrix operations.

In addition, a solid understanding of In addition, a solid understanding of recursion is helpful in analyzing the time recursion is helpful in analyzing the time complexity of algorithms.complexity of algorithms.

Mathematical induction.Mathematical induction. Recurrence relations.Recurrence relations.

Recursion-related analysis techniques include:Recursion-related analysis techniques include:

Page 2: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 22

Recursive Backtracking: Flood Fill Recursive Backtracking: Flood Fill AlgorithmAlgorithmStarting with a “seed” pixel that’s inside a polygonal region, Starting with a “seed” pixel that’s inside a polygonal region, recursively visit the four adjacent pixels, coloring any that recursively visit the four adjacent pixels, coloring any that haven’t been colored, and that aren’t on the polygon’s haven’t been colored, and that aren’t on the polygon’s boundary. Reaching the boundary is the recursion’s boundary. Reaching the boundary is the recursion’s termination condition.termination condition.

Seed Seed pixelpixel

Boundary Boundary pixelpixel

LRUD-visited LRUD-visited pixelpixel

voidvoid floodfill( floodfill(intint x, x, intint y) y){{ ifif (!filled(x,y)) (!filled(x,y)) {{ color(x,y);color(x,y); floodfill(x-1,y); floodfill(x-1,y); // Left// Left floodfill(x+1,y); floodfill(x+1,y); // Right// Right floodfill(x,y-1); floodfill(x,y-1); // Up// Up floodfill(x,y+1); floodfill(x,y+1); // Down// Down }}}}

Page 3: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 33

Recursive GrammarsRecursive GrammarsLanguages, in particular Languages, in particular programming languages, are programming languages, are defined by their defined by their grammarsgrammars, sets of , sets of recursive rules which provide recursive rules which provide syntax.syntax.

Example: A Simple Example: A Simple Calculator Calculator GrammarGrammar

program:program:ENDENDexpr_list ENDexpr_list END

expr_list:expr_list:expression ;expression ;expression ; expr_listexpression ; expr_list

expression:expression:term + expressionterm + expressionterm – expressionterm – expressiontermterm

term:term:primary / termprimary / termprimary * termprimary * termprimaryprimary

primary:primary:NUMBERNUMBERNAMENAMENAME = expressionNAME = expression- primary- primary( expression )( expression )

Using this grammar, the following is a syntactically correct calculator program: pi = 3.1416; rad = 2.5; ht = 10; area = pi * rad * rad; surfacearea = 2 * (area + pi * rad * ht); ENDRecursive grammars are also Recursive grammars are also

prominent in more sophisticated prominent in more sophisticated languages, making the following languages, making the following language features possible:language features possible:• nested loops, conditionals, function nested loops, conditionals, function callscalls• cascaded operators (<<, >>, =, etc.)cascaded operators (<<, >>, =, etc.)• multiple cases in a switch statementmultiple cases in a switch statement

Page 4: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 44

Recursive Matrix OperationsRecursive Matrix OperationsMany matrix operations can be defined recursively, using Many matrix operations can be defined recursively, using combinations of submatrix operations to implement the large combinations of submatrix operations to implement the large matrix operation.matrix operation.Example: DeterminantsExample: Determinants

Note that a Note that a matrix’s matrix’s determinant determinant is used to is used to determine, determine, among other among other things, things, whether it’s whether it’s invertible.invertible.

Page 5: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 55

/////////////////////////////////////// Class definition file: matrix.h //// The matrix class has two data //// members: a square array of int- //// eger values (all between 0 and //// 9), and an integer indicating //// the array size. Its member //// functions include constructors, //// functions to set and access //// specific array elements, a //// function to access a subarray, //// a recursive determinant func- //// tion, and an output operator. ///////////////////////////////////////

#ifndef MATRIX_H#include <fstream>using namespace std;

typedef int elementType;const int MAX_GRID_SIZE = 7;

class matrix{ public: // Class constructors matrix() {size = 0;} matrix(const matrix &m); matrix(int sz);

// Member functions int getSize() const { return size; } void setElement(int i, int j, elementType item); elementType getElement(int i, int j) { return table[i][j]; } elementType determinant(); friend ostream& operator << (ostream &os, const matrix &m);

protected: // Data members elementType table[MAX_GRID_SIZE] [MAX_GRID_SIZE]; int size;

// Member function matrix minor(int i, int j);};

#define MATRIX_H#endif

Recursive Determinant Program ExampleRecursive Determinant Program Example

Page 6: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 66

////////////////////////////////////////////// Class implementation file: matrix.cpp //// //// The implementation of the copy and //// initializing constructors, the setEle- //// ment, determinant, and minor member //// functions, and the output operator. //////////////////////////////////////////////

#include <cstdlib>#include <cassert>#include <fstream>#include <iomanip>#include <cmath>#include "matrix.h"using namespace std;// Copy constructor: Copies existing mat.//matrix::matrix(const matrix &m){ size = m.size; for (int row = 0; row < m.size; row++) for (int col = 0; col < m.size; col++) table[row][col] = m.table[row][col];}

// Initializing constructor: Sets *this //// up as a sz x sz matrix of zeros. //matrix::matrix(int sz){ size = sz; for (int row = 0; row < sz; row++) for (int col = 0; col < sz; col++) table[row][col] = 0;}

// SetElement Member Function: Sets the //// (i,j) element of the matrix to item. //void matrix::setElement(int i, int j, elementType e){ assert ((0<=i) && (i<size) && (0<=j) && (j<size)); table[i][j] = e;}

// Determinant Member Function: Calculates //// & returns the determinant of the matrix. //elementType matrix::determinant(){ elementType value = 0; if (size == 1) return table[0][0]; for (int col = 0; col < size; col++) { value += (elementType)pow(-1, 0+col) * table[0][col] * minor(0, col).determinant(); } return value;}

Notice how the size×size matrix is

being evaluated recursively by using

the top row to expand into size (size-

1)×(size-1) submatrices.

Page 7: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 77

// Minor Member Function: If *this is // // an nXn matrix, then this returns //// the (n-1)X(n-1) matrix that is //// *this w/row i & column j removed. //matrix matrix::minor(int i, int j){ int subrow, subcol; assert (size > 1); matrix submat(size-1); subrow = 0; for (int row = 0; row < size; row++) { subcol = 0; if (row != i) { for (int col = 0; col < size; col++) if (col != j) { submat.setElement(subrow, subcol, table[row][col]); subcol++; } subrow++; } } return submat;}

// Output Operator: Outputs matrix //// as a grid of size rows with //// size columns in each row. //ostream& operator << (ostream &os, const matrix &m){ for (int row = 0; row < m.getSize(); row++) { for (int col = 0; col < m.getSize(); col++) os << setw(4) << m.table[row][col]; os << endl; } return os;}

Page 8: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 88

////////////////////////////////////////////////////// Program file: matrixDriver.cpp //// This program tests the matrix class by //// creating a random matrix of a user-specified //// size, outputting it, & taking its determinant. //////////////////////////////////////////////////////

#include <iostream>#include <iomanip>#include <ctime>#include <cstdlib>#include "matrix.h"using namespace std;int generateRandomNumber(int lowerBound, int upperBound);

// The main function randomly generates & outputs //// a square matrix,, & determines its determinant.//void main(){ int gridSize; cout << "SPECIFY THE MATRIX SIZE (a positive " << "integer less than " << MAX_GRID_SIZE+1 << "): "; cin >> gridSize; while ((gridSize<1) || (gridSize>MAX_GRID_SIZE)) { cout << "SORRY, ONLY VALUES BETWEEN 1 AND " << MAX_GRID_SIZE << " ARE ACCEPTED>\n“; cout << "SPECIFY THE MATRIX SIZE (a positive " << "integer less than " << MAX_GRID_SIZE+1 << "): "; cin >> gridSize; }

matrix grid(gridSize); for (int row=0; row<gridSize; row++) for (int col=0; col<gridSize; col++) grid.setElement(row, col, generateRandomNumber(0,9)); cout << endl << "MATRIX:" << endl << grid << endl << endl; cout << "DETERMINANT: " << grid.determinant() << endl << endl;}

// The generateRandomNumber function //// randomly generates an integer in the //// range between the parameterized low- //// erBound & upperBound values (inclu- //// sive). The first time it is called, //// it seeds stdlib.h's random number //// generation function rand(). //int generateRandomNumber(int lowerBound, int upperBound){ static bool firstTime = true; long int randomNumberSeed; if (firstTime) { time(&randomNumberSeed); srand(randomNumberSeed); firstTime = false; } return (lowerBound + int((upperBound - lowerBound) * (float(rand()) / RAND_MAX)));}

Page 9: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 99

Page 10: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 1010

A mathematical “cousin” to recursion is the concept of A mathematical “cousin” to recursion is the concept of inductioninduction..

Step One: Prove The Base CaseStep One: Prove The Base CaseFormally demonstrate that it’s true for that Formally demonstrate that it’s true for that smallest value, smallest value, nn00..

Step Two: Assume For Some General CaseStep Two: Assume For Some General CaseAssume that the it’s true for all values Assume that the it’s true for all values through through kk, where , where kk is at least is at least nn00..

Step Three: Prove For The Next CaseStep Three: Prove For The Next CaseUse the assumption that it’s true for Use the assumption that it’s true for smaller cases to prove that it’s also true for smaller cases to prove that it’s also true for kk+1.+1.

Mathematical InductionMathematical Induction

When you want to prove that something is true for all When you want to prove that something is true for all integer values, beginning at a specific value ninteger values, beginning at a specific value n00, perform , perform the following steps:the following steps:

Page 11: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 1111

Induction ExampleInduction ExampleTheorem A:Theorem A: i = 1,n i = 1,n i = ½n(n + 1) for all n i = ½n(n + 1) for all n

1.1.Proof (by induction):Proof (by induction):Step One (Prove for the base case):Step One (Prove for the base case):

For n = 1, For n = 1, i = 1,1 i = 1,1 i = 1 = ½(1)(1 + 1).i = 1 = ½(1)(1 + 1).Step Two (Assume for some general case):Step Two (Assume for some general case):

Assume for n = k: Assume for n = k: i = 1,k i = 1,k i = ½k(k + 1).i = ½k(k + 1).Step Three (Prove for the next case):Step Three (Prove for the next case):

Prove for n = k + 1:Prove for n = k + 1: i = 1,k+1 i = 1,k+1 i i = (k + 1) + = (k + 1) + i = 1,k i = 1,k ii

= (k + 1) + ½k(k + 1)= (k + 1) + ½k(k + 1) (by the assumption for (by the assumption for

case k)case k)= ½(2)(k + 1) + ½k(k + 1)= ½(2)(k + 1) + ½k(k + 1)= ½(k + 1)(k + 2)= ½(k + 1)(k + 2)= ½(k + 1)((k + 1) + 1).= ½(k + 1)((k + 1) + 1).

Page 12: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 1212

To prove that To prove that i = 1,n i = 1,n i = ½n(n + 1) for all n i = ½n(n + 1) for all n 1, we 1, we started by proving that it was true for n = 1.started by proving that it was true for n = 1.

Once we accomplished that, we assumed that it was Once we accomplished that, we assumed that it was true for some arbitrary value k and then proved true for some arbitrary value k and then proved that that thatthat made it true for the next value: k + 1. made it true for the next value: k + 1.

In essence, this last proof causes the truth of the In essence, this last proof causes the truth of the theorem to “cascade” through all remaining theorem to “cascade” through all remaining values.values.

Why Does Induction Work?Why Does Induction Work?

TRUEFOR

n = 1:1 =

½(1)(2)

Letting k =

1 TRUEFOR

n = 2:1 + 2 =½(2)(3)

Letting k =

2 TRUEFOR

n = 3:1+2+3 =½(3)(4)

Letting k =

3

Proof that if it’s true for n = Proof that if it’s true for n = k, then it’s also true for n = k k, then it’s also true for n = k

+ 1+ 1

TRUEFOR

n = 4:1+2+3+4 =

½(4)(5)

Letting k =

4 TRUEFOR

n = 5 :1+2+3+4+5 =½(5)(6)

andso

on...

Page 13: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 1313

Theorem Z:Theorem Z: For any group of n people, all n have the For any group of n people, all n have the same height.same height.

What’s What’s WrongWrong With This Induction? With This Induction?

Proof (by induction):Proof (by induction):Step One (Prove for the base case):Step One (Prove for the base case):

For n = 1, the group consists of a single For n = 1, the group consists of a single person, so the entire group obviously has the person, so the entire group obviously has the same height.same height.Step Two (Assume for some general case):Step Two (Assume for some general case):

Assume for n = k: Any group of k people have Assume for n = k: Any group of k people have the same height.the same height.

Step Three (Prove for the next case):Step Three (Prove for the next case):Prove for n = k + 1:Prove for n = k + 1:Given a group of k + 1 people, remove one Given a group of k + 1 people, remove one

person. The resulting group of k people person. The resulting group of k people must, by the inductive hypothesis, have the must, by the inductive hypothesis, have the same height.same height.

Reinsert the person that was removed and then Reinsert the person that was removed and then remove a different person. The resulting remove a different person. The resulting group of k people must also have the same group of k people must also have the same height.height.

Thus, all k + 1 people must have the same Thus, all k + 1 people must have the same height!height!

Page 14: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 1414

intint powerOf2( powerOf2(const intconst int &n) &n){{ ifif (n == 0) (n == 0) returnreturn 1; 1; returnreturn powerOf2(n-1) + powerOf2(n-1); powerOf2(n-1) + powerOf2(n-1);}}

Recurrence RelationsRecurrence RelationsOne of the bridges between recursion and One of the bridges between recursion and

induction is the induction is the recurrence relationrecurrence relation, which can , which can be used to determine the execution time of a be used to determine the execution time of a recursive function.recursive function.

Assuming that the execution time for arithmetic Assuming that the execution time for arithmetic operations, condition checking, and returning are all operations, condition checking, and returning are all the same, let’s also assume that there is a function T(n) the same, let’s also assume that there is a function T(n) such that it takes T(k) time to execute such that it takes T(k) time to execute powerOf2powerOf2(k).(k). Examination of the code Examination of the code above allows us to above allows us to conclude the following two conclude the following two facts:facts:

T(T(00) = ) = 22T(k) = T(k) = 55 + + 22T(k-T(k-11) ) for allfor all k > k >

00

Page 15: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 1515

Using mathematical induction, we can prove that:Using mathematical induction, we can prove that:

T(T(00) = ) = 22T(k) = T(k) = 55 + + 22T(k-T(k-11) ) for allfor all k k

> > 00

T(k) = T(k) = 7(27(2kk)-5)-5 for allfor all k k 00

Step One (Prove for the base case):Step One (Prove for the base case):For n = 0, we already know that T(0) = 2, and 7(2For n = 0, we already know that T(0) = 2, and 7(200)-5 also evaluates )-5 also evaluates

to 2.to 2.Step Two (Asume for some general case):Step Two (Asume for some general case):

Assume for n = k: T(k) = 7(2Assume for n = k: T(k) = 7(2kk)-5.)-5.

Step Three (Prove for the next case):Step Three (Prove for the next case):Prove for n = k + 1:Prove for n = k + 1:We know that T(k+1) = 5 + 2T(k), and we’re assuming that T(k) = We know that T(k+1) = 5 + 2T(k), and we’re assuming that T(k) =

7(27(2kk)-5, so we can conclude that T(k+1) = 5 + 2(7(2)-5, so we can conclude that T(k+1) = 5 + 2(7(2kk)-5) = 7(2)-5) = 7(2k+1k+1)-)-5, which is what we wanted.5, which is what we wanted.

Page 16: Chapter 5 Recursion

CS 240CS 240 Chapter 5 - RecursionChapter 5 - Recursion Page Page 1616

intint powerOf2( powerOf2(const intconst int &n) &n){{ ifif (n == 0) (n == 0) returnreturn 1; 1; returnreturn 2*powerOf2(n-1); 2*powerOf2(n-1);}}

One More Example...One More Example...Let’s try the same trick on this alternate form of the Let’s try the same trick on this alternate form of the

function.function.

Using the same assumptions as before, we get the following Using the same assumptions as before, we get the following recurrence relation:recurrence relation:

T(T(00) = ) = 22T(k) = T(k) = 44 + T(k- + T(k-11) ) for allfor all k k

> > 00This time, however, mathematical induction tells us This time, however, mathematical induction tells us

that:that: T(k) = T(k) = 44kk+2+2 for allfor all k k 00