lecture09 recursion

57
1 Chapter 9 Recursion

Upload: hariz-mustafa

Post on 05-Dec-2014

458 views

Category:

Documents


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Lecture09 recursion

1

Chapter 9Recursion

Page 2: Lecture09 recursion

2

Recursive Functions

• Recursive functions are functions that call themselves.

• Data structures, especially linked implementations of binary trees, sometimes use recursive functions.

Page 3: Lecture09 recursion

3

Example: Factorial Function

• The factorial function is often written as a recursive function.

• The factorial of a positive integer is the product of all positive integers less than or equal to the number.5 factorial is written 5!5! = 5 * 4 * 3 * 2 * 1 = 1203! = 3 * 2 * 1 = 60! is defined to be 1

Page 4: Lecture09 recursion

4

Factorial Function

1 int factorial( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial( num – 1 );6 }

The recursive function call

Page 5: Lecture09 recursion

5

What Happens When a Function Calls Itself?

• When a function calls itself, it is not actually executing itself again.

• Instead, another function is made which is identical.

• Then, that function is called from the recursive function call.

• This will be illustrated in the slides that follow…

Page 6: Lecture09 recursion

6

x = factorial( 4 );

A function call that should produce 24 as a result and assign it to x.

Recursive Process

Page 7: Lecture09 recursion

7

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( num – 1 );}

4 replaces each occurrence of num

Recursive Process(cont.)

4

4 4

4

4 is passed into num

Page 8: Lecture09 recursion

8

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( 3 );}

Recursive Process(cont.)

4

4 4

A recursive function call is made – an identical factorial function is made and called.

Page 9: Lecture09 recursion

9

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( num – 1 );}

Recursive Process(cont.)

4

4 4

3 replaces each occurrence of num3 3

3 3

3 is passed into num

Page 10: Lecture09 recursion

10

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4

3 3

3

A recursive function call is made – an identical factorial function is made and called.

Page 11: Lecture09 recursion

11

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( num – 1 );}

2 replaces each occurrence of num

2 2

2 2

3 3

3

2 gets passed into num

Page 12: Lecture09 recursion

12

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( 1 );}

2 2

2

A recursive function call is made – an identical factorial function is made and called.

3 3

3

Page 13: Lecture09 recursion

13

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 1 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( num – 1 );}

1 is passed into num

1 1

1 1

3 3

3

2 2

2

Page 14: Lecture09 recursion

14

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 1 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( num – 1 );}

Where is 1 returned?

3 3

3

2 2

2

1 1

1 1

Page 15: Lecture09 recursion

15

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 1 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( num – 1 );}

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4

3 3

3

2 2

2

1 1

1 1

The 1 replaces the function call that called this function (just as we would expect with any function call)

Page 16: Lecture09 recursion

16

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * 1;}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;return num * factorial( num – 1 );}

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4

The last function has finished

3 3

3

2 2

2

1 1

1 1

Page 17: Lecture09 recursion

17

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return 2;}

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4

The execution of this return statement can now resume

3 3

3

2 2

Page 18: Lecture09 recursion

18

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return 2;}

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 2 );}

Recursive Process(cont.)

4

4 4

3 3

3

2 2

It now returns 2 back to the function call that called this function.

Page 19: Lecture09 recursion

19

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * factorial( 3 );}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return 6;}

Recursive Process(cont.)

4

4 4

3 3

Page 20: Lecture09 recursion

20

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return num * 6;}

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return 6;}

Recursive Process(cont.)

4

4 4

3 3

Page 21: Lecture09 recursion

21

x = factorial( 4 );

int factorial( int num ){if ( num == 0 || num == 1 )

return 1;

return 24;}

Recursive Process(cont.)

4 4

Page 22: Lecture09 recursion

22

x = 24;

Recursive Process(cont.)

x gets the correct value of 24

Page 23: Lecture09 recursion

23

Base Case

1 int factorial( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial( num – 1 );6 }

Notice that these lines stopped the recursion – without these lines, the function will call itself over and over again (infinite recursion)

Page 24: Lecture09 recursion

24

Base Case (cont.)

1 int factorial( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial( num – 1 );6 }

These lines are called the base case – the case that stops the recursion.

Page 25: Lecture09 recursion

25

Recursive Case

1 int factorial( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial( num – 1 );6 }

This line that produces a recursive function call is called the recursive case.

All recursive functions have a base case and a recursive case (and sometimes more than one of each).

Page 26: Lecture09 recursion

26

What If?

1 int factorial( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial( num – 1 );6 }

If one makes a mistake and inputs a negative number into this function:

factorial( -2 );

what will happen?

Page 27: Lecture09 recursion

27

Infinite Recursion

1 int factorial( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial( num – 1 );6 }

If one makes a mistake and inputs a negative number into this function:

factorial( -2 );

what will happen? Infinite recursion.

Page 28: Lecture09 recursion

28

Drivers

1 int factorial2( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial2( num – 1 );6 }

In order to prevent this problem, we can change the name of this function to factorial2…

Page 29: Lecture09 recursion

29

Drivers (cont.)

1 int factorial2( int num )2 {3 if ( num == 0 || num == 1 )4 return 1;5 return num * factorial2( num – 1 );6 }

and then write a factorial function, called a driver, to call this function…

Page 30: Lecture09 recursion

30

Drivers (cont.)

int factorial( int num ){if ( num < 0 ) {

cout << “The factorial of a negative number is undefined”

<< endl; return 0; }

return factorial2( num );}

Page 31: Lecture09 recursion

31

Guidelines

• There must be a base case that stops recursion.• Each recursive call should approach the base

case.• The recursive function call should work for the

base case.• The recursive function call should work for the

case next to the base case.• The recursive function should make logical

sense, assuming that the recursive function call inside it does everything it should do.

Page 32: Lecture09 recursion

32

Example

• When you know the case next to the base case works, you know factorial( 2 ) works.

• Since 3! = 3 * factorial( 2 ), you know factorial( 3 ) works – makes logical sense.

• Since 4! = 4 * factorial( 3 ) and you know that factorial( 3 ) works, you know that factorial( 4 ) works.

• Etc., etc.

Page 33: Lecture09 recursion

33

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

Searching for a Mercedes in the linked list:Car mercedes, foundCar;…bool found = search( start, foundCar, mercedes );

Page 34: Lecture09 recursion

34

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

Overloaded operator in Car struct

Page 35: Lecture09 recursion

35

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

Returns true if in list; returns false otherwise.

Page 36: Lecture09 recursion

36

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

If true is returned, foundItem will be assigned Mercedes (passed by reference on each recursive call)

Page 37: Lecture09 recursion

37

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

Two base cases

Page 38: Lecture09 recursion

38

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

Don’t forget the return ( it is a common mistake)…

Page 39: Lecture09 recursion

39

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

It passes the true/false value (from base cases) back through the succession of recursive function calls.

Page 40: Lecture09 recursion

40

Recursion on a Linked List (cont.)

bool search( Node<T> *ptr, T& foundItem, T& target){

if ( ptr == NULL )return false;

if ( ptr->info == target ) {foundItem = ptr->info;return true;}

return search( ptr->next, foundItem, target );}

Advances pointer in a recursive function call

Page 41: Lecture09 recursion

41

Recursion on a Linked List (cont.)

1 void discount( Node<T> *ptr )2 {3 if ( ptr != NULL ) {4 ptr->info.price -= 0.1 * ( ptr->info.price );5 discount( ptr->next );6 }7 }

Discounts all Car prices in a linked list by 10%

Page 42: Lecture09 recursion

42

Recursion on a Linked List (cont.)

1 void discount( Node<T> *ptr )2 {3 if ( ptr != NULL ) {4 ptr->info.price -= 0.1 * ( ptr->info.price );5 discount( ptr->next );6 }7 }

Recursive call – no return necessary (void return type)

Page 43: Lecture09 recursion

43

Recursion on a Linked List (cont.)

1 void discount( Node<T> *ptr )2 {3 if ( ptr != NULL ) {4 ptr->info.price -= 0.1 * ( ptr->info.price );5 discount( ptr->next );6 }7 }

Where is the base case?

Page 44: Lecture09 recursion

44

Recursion on Linked Lists (cont.)

1 void discount( Node<T> *ptr )2 {3 if ( ptr != NULL ) {4 ptr->info.price -= 0.1 * ( ptr->info.price );5 discount( ptr->next );6 }7 }

The base case exists, it just does not need to be written. When ptr == NULL, it is the base case. The only thing that needs to be done for the base case is to return.

Page 45: Lecture09 recursion

Tower of Hanoi

• Three pegs are provided to hold disks. The first peg has a stack of n disks that are arranged from bottom to top by decreasing size.

• The goal is to move the stack from the first peg to the last peg under the following rules:– Exactly one disk is moved at a time.– A larger disk should never be placed above a smaller

disk.

45

Page 46: Lecture09 recursion

Tower of Hanoi (cont.)

• Example: Initial stack of 3 disks all placed at Peg A.

46

3

2

1

Peg A Peg B Peg C

Page 47: Lecture09 recursion

Tower of Hanoi (cont.)

• Step 1: Move disk 1 from Peg A to Peg C.

47

3

2

Peg A Peg B Peg C

1

Page 48: Lecture09 recursion

Tower of Hanoi (cont.)

• Step 2: Move disk 2 from Peg A to Peg B.

48

3Peg A Peg B Peg C

2 1

Page 49: Lecture09 recursion

Tower of Hanoi (cont.)

• Step 3: Move disk 1 from Peg C to Peg B.

49

3Peg A Peg B Peg C

2

1

Page 50: Lecture09 recursion

Tower of Hanoi (cont.)

• Step 4: Move disk 3 from Peg A to Peg C.

50

3Peg A Peg B Peg C

2

1

Page 51: Lecture09 recursion

Tower of Hanoi (cont.)

• Step 5: Move disk 1 from Peg B to Peg A.

51

3Peg A Peg B Peg C

2 1

Page 52: Lecture09 recursion

Tower of Hanoi (cont.)

• Step 6: Move disk 2 from Peg B to Peg C.

52

3Peg A Peg B Peg C

2

1

Page 53: Lecture09 recursion

Tower of Hanoi (cont.)

• Step 7: Move disk 1 from Peg A to Peg C.

53

3Peg A Peg B Peg C

2

1

Page 54: Lecture09 recursion

Tower of Hanoi (cont.)

54

• Goal achieve: The stack is moved to Peg C.

Peg A Peg B Peg C

3

2

1

Page 55: Lecture09 recursion

55

Tower of Hanoi (cont.)

• If there is 1 disk in the stack, the total number of moves is 1 (21 - 1).

• If 2 disks … moves is 3 (22 - 1).• If 3 disks … moves is 7(23 - 1).• Hence, if there are n disks…, the total number of

moves is 2n – 1.

Page 56: Lecture09 recursion

56

Tower of Hanoi (cont.)

1 void TowerOfHanoi (int n, 2 string source, string temp, string destination) {3 if (n == 1) // base case4 cout << "Move disk " << n << " from " 5 << source << " to " << destination << endl;6 else {7 TowerOfHanoi (n - 1, source, destination, temp);8 cout << "Move disk " << n << " from " 9 << source << " to " << destination << endl;10 TowerOfHanoi (n - 1, destination, temp, source);11 }12 }

Page 57: Lecture09 recursion

References

• Childs, J. S. (2008). Recursion. C++ Classes and Data Structures. Prentice Hall.

57