cmsc 2021 recursion recursive definition – one that defines something in terms of itself recursion...

50
CMSC 202 1 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem in to one or more subproblems that are similar in form to the original problem. Either the problem or the associated data can be recursive in nature

Upload: morgan-craig

Post on 29-Dec-2015

222 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 1

Recursion

Recursive Definition – one that defines something in terms of itself

Recursion – A technique that allows us to break down a problem in to one or more subproblems that are similar in form to the original problem.Either the problem or the associated data can be recursive in nature

Page 2: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 2

Iterative FactorialIterative definition

N! = N * (N-1) * (N-2) * … * 3 * 2 * 1

int factorial (int n) { int i, result; result = 1; for (i = 1; i <= n; i++) { result = result * i; } return ( result );}

Page 3: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 3

Recursive FactorialRecursive N! definition N! = 1 if N = 0 = N * (N-1)! Otherwise

int factorial ( int n) { if (n == 0) return (1);

return (n * factorial(n - 1) );}

Page 4: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 4

Iterative vs Recursive factorial

Iterative

1. 2 local variables

2. 3 statements

3. Saves solution in an intermediate variable

Recursive

1. No local variables

2. One statement

3. Returns result in single expression

Recursion simplifies factorial by making the computer do the work.

What work and how is it done?

Page 5: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 5

How does it work?

Each recursive call creates an “activation record” which contains

local variables and parameters

return address

and is saved on the stack.

Page 6: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 6

Iterative Power

Iterative definition XN = X * X *X ….. * X (N factors)

double power(double number, int exponent){ double p = 1;

for (int i = 1; i <= exponent; i++) p = p * p; return (p);}

Page 7: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 7

Recursive Power

Recursive definitionXN = 1 if N = 0

= X * X(N-1) otherwisedouble power(double number, int exponent)// Precondition: exponent >= 0{ if (exponent == 0) return (1);

return (number * power(number, exponent-1));}

Page 8: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 8

Recursive String Reversal

void RString (char *s, int len){ if (len <= 0) return;

RString (s+1, len-1);

cout << *s ;}

Page 9: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 9

Recursive Data Structures

Array -- a set of data elements store in contiguous memory cells

Array -- zero elements OR

a single data element OR

an array followed by a single element

Page 10: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 10

Iteratively Sum an Array

int SumArray (int a[ ], int size)

{

int j, sum = 0;

for ( j = 0; j < size; j++ )

sum += a[ j ];

return sum;

}

Page 11: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 11

Recursively Sum an Arrayint SumArray ( int a [ ], int size)

{

if (size == 0)

return 0;

else

return array[ size – 1] + SumArray (a, size – 1);

}

Page 12: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 12

Approach to Writing Recursive Functions

Using “factorial” as an example,

1. Write the function header so that you are sure what the function will do and how it will be

called.

[For factorial, we want to send in the integer for which we want to compute the factorial. And we want to receive the integer result back.]

int factorial(int n)

Page 13: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 13

Approach (cont’d)

2. Decompose the problem into subproblems (if necessary).

For factorial, we must compute (n-1)!

3. Write recursive calls to solve those subproblems whose form is similar to that of the original problem.

There is a recursive call to write:

factorial(n-1) ; ]

Page 14: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 14

Approach (cont’d)

4. Write code to combine, augment, or modify the results of the recursive call(s) if necessary to construct the desired return value or create the desired side effects.

When a factorial has been computed, the result must be multiplied by the current value of the number for which the factorial was taken:

return (n * factorial(n-1));

Page 15: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 15

Approach (cont’d)

5. Write base case(s) to handle any situations that are not handled properly by the recursive portion of the program.

The base case for factorial is that if n=0, the factorial is 1:

if (n == 0) return(1);

Page 16: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 16

Ensuring that Recursion Works

Using “factorial” as an example,

1. A recursive subprogram must have at least one base case and one recursive case (it's OK to have more than one base case and/or more than one recursive case).

The first condition is met, because if (n==0) return 1 is a base case, while the "else" part includes a recursive call (factorial(n-1)).

Page 17: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 17

Does It Work? (cont’d)

2. The test for the base case must execute before the recursive call.

If we reach the recursive call, we must have already evaluated if (n==0); this is the base case test, so this criterion is met.

Page 18: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 18

Does It Work? (cont’d)

3. The problem must be broken down in such a way that the recursive call is closer to the base case than the top-level call.

The recursive call is factorial(n-1). The argument to the recursive call is one less than the argument to the top-level call to factorial. It is, therefore, “closer” to the base case of n=0.

Page 19: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 19

Does It Work? (cont’d)

4. The recursive call must not skip over the base case. Because n is an integer, and the recursive call reduces n by just one, it is not possible to skip over the base case.

Page 20: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 20

Does It Work? (cont’d)

5. The non-recursive portions of the subprogram must operate correctly.

Assuming that the recursive call works properly, we must now verify that the rest of the code works properly. We can do this by comparing the code with our definition of factorial. This definition says that if n=0 then n! is one. Our function correctly returns 1 when n is 0. If n is not 0, the definition says that we should return (n-1)! * n. The recursive call (which we now assume to work properly) returns the value of n-1 factorial, which is then multiplied by n. Thus, the non--recursive portions of the function behave as required.

Page 21: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 21

Recursion vs. Iteration

Recursion

Usually less code – algorithm can be easier to follow (Towers of Hanoi, binary tree traversals, flood fill)

Some mathematical and other algorithms are naturally recursive (factorial, summation, series expansions, recursive data structure algorithms)

Page 22: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 22

Recursion vs. Iteration (cont’d)

Iteration

Use when the algorithms are easier to write, understand, and modify (especially for beginning programmers)

Generally, runs faster because there is no stack I/O

Sometimes are forced to use iteration because stack cannot handle enough activation records (power(2, 5000))

Page 23: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 23

Direct RecursionA C function is directly recursive if it contains an explicit call to itself

Int foo (int x)

{

if ( x <= 0 ) return x;

return foo ( x – 1);

}

Page 24: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 24

Indirect RecursionA C function foo is indirectly recursive if it contains a call to another function that ultimately calls foo.

int foo (int x){

if (x <= 0) return x;

return bar(x);

}

int bar (int y)

{

return foo (y – 1);

}

Page 25: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 25

Tail Recursion

A recursive function is said to be tail recursive if there is no pending operations performed on return from a recursive call

Tail recursive functions are often said to “return the value of the last recursive call as the value of the function”

Page 26: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 26

factorial is non-tail recursive

int factorial (int n){ if (n == 0) return 1; return n * factorial(n – 1);}

Note the “pending operation” (namely the multiplication) to be performed on return from each recursive call

Page 27: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 27

Tail recursive factorialint fact_aux (int n, int result) {

if (n == 1) return result;return fact_aux (n – 1, n * result);

}

factorial (int n) {

return fact_aux (n, 1);

}

Page 28: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 28

Linear Recursion A recursive function is said to be linearly recursive when no pending operation invokes another recursive call to the function.

int factorial (int n){ if (n == 0) return 1; return n * factorial ( n – 1);}

Page 29: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 29

Linear Recursive Count_42s

int count_42s(int array[ ], int n){ if (n == 0) return 0;

if (array[ n-1 ] != 42) { return (count_42s( array, n-1 ) ); }

return (1 + count_42s( array, n-1) );}

Page 30: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 30

Tree Recursion

A recursive function is said to be tree recursive (or non-linearly recursive when the pending operation does invoke another recursive call to the function.

The Fibonacci function fib provides a classic example of tree recursion.

Page 31: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 31

Fibonacci NumbersThe Fibonacci numbers can be recursively defined by the rule:

fib(n) = 0 if n is 0, = 1 if n is 1, = fib(n-1) + fib(n-2) otherwise

For example, the first seven Fibonacci numbers are Fib(0) = 0 Fib(1) = 1 Fib(2) = Fib(1) + Fib(0) = 1 Fib(3) = Fib(2) + Fib(1) = 2 Fib(4) = Fib(3) + Fib(2) = 3 Fib(5) = Fib(4) + Fib(3) = 5 Fib(6) = Fib(5) + Fib(4) = 8

Page 32: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 32

Tree Recursive Fibonacci// Note how the pending operation (the +)// needs a 2nd recursive call to fib

int fib(int n){ if (n == 0) return 0;

if (n == 1) return 1;

return ( fib ( n – 1 ) + fib ( n – 2 ) );}

Page 33: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 33

Tree Recursive Count_42sint count_42s(int array[ ], int low, int high){ if ((low > high) || (low == high && array[low] != 42)) { return 0 ; }

if (low == high && array[low] == 42) { return 1; }

return (count_42s(array, low, (low + high)/2) + count_42s(array, 1 + (low + high)/2, high)) );}

Page 34: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 34

Converting Recursive Functions to Tail Recursion

A non-tail recursive function can often be converted to a tail recursive function by means of an “auxiliary” parameter that is used to form the result.

The idea is to incorporate the pending operation into the auxiliary parameter in such a way that the recursive call no longer has a pending operations (is tail recursive)

Page 35: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 35

Tail Recursive Fibonacciint fib_aux ( int n, int next, int result ) { if ( n == 0 ) return result; return ( fib_aux ( n - 1, next + result, next ));}

int fib ( int n ){ return fib_aux ( n, 1, 0 );}

Page 36: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 36

Converting Tail Recursive Functions to Iterative

Let’s assume that any tail recursive function can be expressed in the general form

F ( x ) {

if ( P( x ) ) return G( x );

return F ( H( x ) );

}

Page 37: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 37

Tail Recursive to Iterative(cont’d)

P( x ) is the base case of F(x)

If P(x) is true, then the value of F(x) is the value of some other function, G(x).

If P(x) is false, then the value of F(x) is the value of the function F on some other value H(x).

Page 38: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 38

Tail Recursive to Iterative(cont’d)

F( x ) {

int temp_x; while ( P(x) is not true ) {

temp_x = x;x = H (temp_x);

} return G ( x );

Page 39: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 39

Example – tail recursive factorial

int fact_aux (int n, int result){ if (n == 1) return result; return fact_aux (n – 1, n * result)}

F = fact_auxx is really two params – n and resultvalue of P(n, result) is value of (n == 1)value of G(n, result) is resultvalue of H(n, result) is (n – 1, n * result)

Page 40: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 40

Iterative factorialint fact_aux (int n, int result) { int temp_n, temp_result;

while ( n != 1 ) { // while P(x) not truetemp_n = n; // temp_x = x (1)

temp_result = result; // temp_x = x (2)n = temp_n – 1; // H (temp_x) (1) result = temp_n * temp_result; // H (temp_x) (2)

} return result; // G (x)

}

Page 41: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 41

Converting Iteration to Tail Recursion

Just like it’s possible to convert tail-recursion into iteration, it’s possible to convert any iterative loop into the combination of a recursive function and a call to that function

Page 42: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 42

A while-loop exampleThe following code fragment uses a while loop to read values into an integer array until EOF occurs, counting the number of integers read.

nt nums [MAX];int count = 0;

while (scanf (“%d”, &nums[count]) != EOF)count++;

Page 43: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 43

While loop example (cont’d)

The key to implementing the loop using tail recursion is to determine which variables capture the “state” of the computation and use these variables as parameters to the tail recursive subprogram.

count – the number of integers read so farnums -- the array that stores the integers

Page 44: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 44

While loop example (cont’d)

Since we are interested in getting the final value for count, we will write a function that returns count as its result.If the termination condition (EOF) is not true, the function increments count, reads a number into nums and calls itself recursively to to input the remainder of the numbers.If the termination condition is true, the function simply returns the final value of count.

Page 45: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 45

While loop example (cont’d)

int read_nums (int count, int nums[ ] ){ if (scanf (“%d”, &nums[count] != EOF))

return read_nums (count + 1, nums); return count;}

Page 46: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 46

While loop example (cont’d)

To call the function, we must pass in the appropriate initial values

count = read_nums (0, nums);

Page 47: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 47

Converting Iteration to Tail recursion

• Determining the variables used by the loop

• Writing tail-recursive function with one parameter for each variable

• Using the loop-termination condition as the base case

Page 48: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 48

Converting Iteration to Tail recursion (cont’d)

•Determining how each variable changes from one iteration to the next and handing the sequence of expressions that represent those changes to the recursive call

• Replacing the iterative loop with a call to the tail recursive function with appropriate initial values

Page 49: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 49

An exercise for the StudentConvert the following for loop that finds the maximum value in an array to be tail recursive. Assume that the function max( ) returns the larger of the two parameters returned to it.

int nums[MAX]; // filled by some other functionint max_num = nums[ 0 ];for (j = 0; j < MAX; j++)

max_num = max (max_num, nums[ j ] );

Page 50: CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem

CMSC 202 50

Floodfill

void Image::floodfill(int x, int y){ if (x < 0 || x >= numRows || y < 0 || y >= numCols) return;

if (a[x][y] == '1') return;

if (a[x][y] == '0') a[x][y] = '1';

floodfill(x+1, y); // Go up floodfill(x-1, y); // Go down floodfill(x, y-1); // Go left floodfill(x, y+1); // Go right}