1 / 68

C++ Programming: Program Design Including Data Structures, Second Edition

C++ Programming: Program Design Including Data Structures, Second Edition. Chapter 16: Recursion. Objectives. In this chapter you will: Learn about recursive definitions Explore the base case and the general case of a recursive definition Discover what is a recursive algorithm

Download Presentation

C++ Programming: Program Design Including Data Structures, Second Edition

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++ Programming: Program Design Including Data Structures, Second Edition Chapter 16: Recursion

  2. Objectives In this chapter you will: • Learn about recursive definitions • Explore the base case and the general case of a recursive definition • Discover what is a recursive algorithm • Learn about recursive functions • Explore how to use recursive functions to implement recursive algorithms C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  3. Recursive Function Call • A recursive call is a function call in which the called function is thesameas the one making the call. • In other words, recursion occurs when a function calls itself! • We must avoid making an infinite sequence of function calls (infinite recursion). expanded by J. Goetz, 2004

  4. Finding a Recursive Solution • Each successive recursive call should bring you closerto a situation in which the answer is known. • A case for which the answer is known (and can be expressed without recursion) is called a base case. • Each recursive algorithm must have at least one base case, as well as • the general(recursive) case – the case for which the solution is expressed in terms of a smaller version of itself. expanded by J. Goetz, 2004

  5. General format formany recursive functions if (some condition for which answer is known) // base case solution statement else// general case recursive function call SOME EXAMPLES . . . expanded by J. Goetz, 2004

  6. Writing a recursive function to find n factorial DISCUSSION The function call Factorial(4) should have value 24, because that is 4 * 3 * 2 * 1 . For a situation in which the answer is known, the value of 0! is 1. So our base case could be along the lines of if ( number == 0 ) return 1; expanded by J. Goetz, 2004

  7. Writing a recursive function to find Factorial(n) Now for the general case . . . The value of Factorial(n) can be written as n * the product of the numbers from (n - 1) to 1, that is, n * (n - 1) * . . . * 1 or, n * Factorial(n - 1) And notice that the recursive call Factorial(n - 1) gets us “closer” to the base case of Factorial(0). expanded by J. Goetz, 2004

  8. Recursive Definition is a definition in which something is defined in terms of smaller version of itself. int Factorial ( int number ) // Recursive Solution // Pre: number is assigned and number >= 0. { if ( number == 0) //(1) base case return 1 ; //(2) else // general case return number * Factorial ( number - 1 ) ; //(3) //includes the simpler problem } expanded by J. Goetz, 2004

  9. int fact ( int number ) // Recursive Solution // Pre: number is assigned and number >= 0. { if ( number == 0) //(1) base case return 1 ; //(2) else // general case return number * fact ( number - 1 ) ; //(3) //includes the simpler problem } //(4) C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  10. Recursive Definitions • Recursion: the process of solving a problem by reducing it to smaller versions of itself • 0! = 1 (1) n! = n x (n-1)! if n > 0 (2) • The definition of factorial in equations (1) and (2) is called a recursive definition • Equation (1) is called the base case • Equation (2) is called the general case C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  11. Recursion • Recursive method • Calls itself directly or indirectly (through another method) • Method knows how to solve only a base case • Methoddivides problem into • Base case • Simplerproblem • Each time method callsitself with a slightly simple problem until convergeson the base case, • then returns to the previous problem, • and a sequence of returns follows up the line until the originalproblemeventually returns the final result to the caller. • Eventually general case gets solved • Gets plugged in, works its way up and solves whole problem C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  12. Iterative Solution int Factorial ( int number ) // Pre: number is assigned and number >= 0. { int fact = 1; for (int i = 2; i <= number; i++) fact = fact * i; return fact ; } C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  13. Recursive Definitions (continued) • Recursive definition: defining a problem in terms of a smaller version of itself • Every recursive definitionmusthave one (or more) base cases • The general casemusteventuallyreduce to a base case • The base case stops the recursion C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  14. Recursive Algorithms • Recursive algorithm: finds a solution by reducing problem to smaller versions of itself • Must have one (or more) base cases • General solutionmust eventuallyreduce to a base case • Recursive function: a function that calls itself • Recursive algorithms are implemented using recursive functions C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  15. Recursive Functions • Thinkof a recursive function as having infinitely many copiesof itself • Every call to a recursive function has • Its owncode • Its own set ofparameters and local variables • After completing a particular recursive call • Control goes backto the calling environment, which is the previous call C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  16. Recursive Functions (continued) • The current (recursive) callmust execute completely before control goes back to the previous call • Execution in the previous call begins from the point immediately following the recursive call • Tail recursive function: A recursive function in which the last statement executed is the recursive call • Example: the function fact C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  17. Direct and Indirect Recursion • A function (A) is called: • Directly recursive if calls itself • Indirectly recursive if calls another function (B) and eventually results in the original function call (A) C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  18. Infinite Recursion • Infinite recursion: every recursive call results in another recursive call • In theory, infinite recursion executes forever • Because computer memory is finite: • Function executes until the system runs out of memory • Results in an abnormal program termination C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  19. Recursion: The Fibonacci Series • Fibonacci series p.901 • Each number in the series is sum of two previous numbers • e.g., 0, 1, 1, 2, 3, 5, 8, 13, 21… • Recursive formula:fibonacci(0) =0fibonacci(1) =1fibonacci(n) = fibonacci(n -1) + fibonacci( n –2 ) • fibonacci(0) and fibonacci(1) are base cases • Performance • Fibonacci-style recursive methods exponentially generate method calls (result in an exponential “explosion” of calls) • Hinders performance • Fib(30) has over 2.7 million method calls • Fib(31) has over 4 million method calls • Fib(32) has over 7 million method calls C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  20. f( 3 ) return f( 2 ) + f( 1 ) return f( 1 ) + f( 0 ) return 1 return 1 return 0 Fig. 6.14 Set of recursive calls to method fibonacci (f in this diagram). C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  21. Design a recursive function • To design a recursive function: • Understand problem requirements • Determine limiting conditions • Identify base cases and provide a direct solution to each base case • Identify general cases and provide a solution to each general case in terms of smaller versions of itself C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  22. 3-Question Method of verifyingrecursive functions: • 1. Base-Case Question: Is there a nonrecursiveway out (solution) of the function? • (ex. Apply to Factorial)Yes. The base case is when N = 0. Factorial is then assigned 1. There is no more processing to do – base case(s) determines stop conditions • 2. Smaller-Caller Question:Does each recursive function call involve a smaller case of the original problemleading to the base case? • (ex. Apply to Factorial)Yes. Each subsequent recursive call sends a decremented value of the parameter, until the value sent is finally 0. • 3. General-Case Question: Assuming each recursive call works correctly, does the whole function work correctly? • (ex. Apply to Factorial)Yes. Assuming that recursive call Factorial (N – 1) gives us the correct value of (n – 1)!. Applying the function to the next value (n – 1) + 1, or n gives the return statement computes N * (N – 1)!, results in the correct formula. Also the formula works for N = 0 see 1 expanded by J. Goetz, 2004

  23. Writing Recursive Functions Guide • Get an exact definition of the problem to be solved. • Determine thesizeof the problem. • The size of the whole problem is expressed in the value(s) of the parameter(s). • Identify and solve the base case(s) in which can be expressed nonrecursively. • This ensures a yes answer to the base-case question. • Identify and solve the general case(s)correctly in terms of a smaller case of thesame problem. • This ensures a yes answer to the smaller-caller andgeneral-case question. C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  24. Another example where recursion comes naturally • From mathematics, we know that 20 = 1 and 25 = 2 * 24 • In general, x0 = 1 and xn = x * xn-1 for integer x, and integer n > 0. • Here we are defining xn recursively, in terms of xn-1 expanded by J. Goetz, 2004

  25. // Recursive definition of power function int Power ( int x, int n ) // Pre: n >= 0. x, n are not both zero // Post: Function value = x raised to the power n. { if ( n == 0 ) return 1; // base case else // general case return ( x * Power ( x , n-1 ) ) ; } Of course, an alternative would have been to use looping instead of a recursive call in the function body. 25 expanded by J. Goetz, 2004

  26. struct ListType – array based structure struct ListType { int length ; // number of elements in the list int info[ MAX_ITEMS ] ; } ; ListType list ; expanded by J. Goetz, 2004

  27. 74 36 . . . 95 75 29 47 . . . list[0] [1] [startIndex] [length -1] Recursive function to determine if value is in list bool ValueInList( ListType list , int value , int startIndex ) ; midexecution: Already searched Needs to be searched index of current element to examine expanded by J. Goetz, 2004

  28. bool ValueInList ( ListType list , int value , int startIndex ) // Searches list for value between positions startIndex // and list.length-1. The size is the number of slots to search. // Pre: list.info[ startIndex ] . . list.info[ list.length - 1 ] // contain values to be searched // Post: Function value = // ( value exists in list.info[ startIndex ] . . list.info[ list.length - 1 ] ) { if ( list.info[startIndex] == value ) // one base case return true ; // found it else if (startIndex == list.length -1 ) // another base case return false ; //the end of the list else // general case – recursive invocation return ValueInList ( list, value, startIndex + 1 ) ;//diminished the //size of the problem } // Note: startIndex acts as an index through the array. //It is incremented on each recursive call and initialized in the original invocation of ValueList 28 expanded by J. Goetz, 2004

  29. Problem Solving Using Recursion p.896 • Base case: The size of the list =1, so it is the largest • General case: List size is greater than 1 • To find the largest element in list[a], list[a + 1], ...,list[b] a. Find largest element in list[a + 1]...list[b] and call it max = maximum (list[a + 1]...list[b]) b. Compare the elements list[a] and max if (list[a] >= max) the largest element in list[a]...list[b] is list[a] otherwise the largest element in list[a]...list[b] is max (go to 1 with reduced # of elements) C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  30. //Largest Element in an Array #include <iostream> usingnamespace std; int largest(constint list[], int lowerIndex, int upperIndex); int main() { int intArray[4] = {5, 10, 12, 8}; cout << "The largest element in intArray: " << largest(intArray, 0, 3); cout << endl; return 0; } intlargest(constint list[], int lowerIndex, int upperIndex) { int max; if (lowerIndex == upperIndex) //size of the sublist is one return list[lowerIndex]; // (1) else { max = largest(list, lowerIndex + 1, upperIndex); if( list[lowerIndex] >= max) return list[lowerIndex]; // (2) else return max; // (3) } } C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  31. Task: Move all disk from the 1st needle to the 3rd needle • The rules for moving disks are as follows: • Only one disk can be moved at a time • The removed disk must be placed on one of the needles • A larger disk cannot be placed on top of a smaller disk C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  32. Tower of Hanoi (continued) • This recursive algorithm translates into the following C++ function: C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  33. C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  34. Static and dynamic storage location • The function’s formal parameters and local variables are • bound to actual addresses in memory at compile time • stored in the fixed number of location The recursive callcannotstore its arguments (actual parameters) in the fixed number of location that were set up at compile time. • The compiler references variables are referenced by the relative( to some address known at run time)addresses (not relative to the location of the function’s code). C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  35. When a function is called... • A transfer of control occurs from the calling block to the code of the function. • It is necessary that there be a return to the correct place in the calling block after the function code is executed. This correct place is called the return address. • Each call to a function generates a new activation record (stack frame). expanded by J. Goetz, 2004

  36. Stack Activation Frames • The activation recordstores the 1. return address for this function call, and also 2. parameters, 3. local variables, 4. register values and 5. the function’s return value, if non-void. • When any function is called, the run-time stack is used. • On this stack is placed an activation record (stack frame) for the function call. • Run-time stack. A data structure that keeps track of activation records during the execution of a program. expanded by J. Goetz, 2004

  37. Activation Record • When a function is invoked, its activation record is pushed onto the run-time stack. • Each nested level of function calls adds another activation record to the stack. • The activation record for a particular function call is popped offthe run-time stackwhen the function ends: • when the final closing brace in the function code is reached, or • when areturn statement is reached in the function code. • At this time the function’s return value, if non-void, it is brought back to the calling block for use there. • The level of recursive calls(limited by memory available) in a program determines how many activation records for this function are pushed onto the run-time stack. C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  38. // memory allocation of space for recursive program // Another recursive function int Func ( int a, int b ) // Pre: a and b have been assigned values // Post: Function value = ?? { int result; if ( b == 0 ) // base case result = 0; else if ( b > 0 ) // first general case result = a + Func ( a , b - 1 ) ) ; // instruction 50 else // second general case result = Func ( - a , - b ) ; //reverse arguments// instruction 70 return result; } int main()// instruction 85 { … x = Func(5, 2); // instruction 100 … } 38 expanded by J. Goetz, 2004

  39. Run-Time Stack Activation Recordsx = Func(5, 2);// original call is instruction 100 FCTVAL ? result ? b 2 a 5 Return Address 100 original call at instruction 100 pushes on this record for Func(5,2) expanded by J. Goetz, 2004

  40. record for Func(5,2) Run-Time Stack Activation Records x = Func(5, 2);// original call at instruction 100 FCTVAL ? result ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 call in Func(5,2) code at instruction 50 pushes on this record for Func(5,1) expanded by J. Goetz, 2004

  41. record for Func(5,1) record for Func(5,2) Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL ? result ? b 0 a 5 Return Address 50 FCTVAL ? result 5+Func(5,0) = ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 call in Func(5,1) code at instruction 50 pushes on this record for Func(5,0) expanded by J. Goetz, 2004

  42. record for Func(5,0) is popped first with its FCTVAL record forFunc(5,1) record for Func(5,2) Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL 0 result 0 b 0 a 5 Return Address 50 FCTVAL ? result 5+Func(5,0) = ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 expanded by J. Goetz, 2004

  43. record for Func(5,1) is popped next with its FCTVAL record forFunc(5,2) Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL 5 result 5+Func(5,0) = 5+ 0 b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 expanded by J. Goetz, 2004

  44. recordfor Func(5,2) is popped last with its FCTVAL Run-Time Stack Activation Recordsx = Func(5, 2);// original call at line 100 FCTVAL 10 result 5+Func(5,1) = 5+5 b 2 a 5 Return Address 100 expanded by J. Goetz, 2004

  45. Show Activation Records for these calls x = Func( - 5, - 3 ); x = Func( 5, - 3 ); What operation does Func(a, b) simulate? expanded by J. Goetz, 2004

  46. Tail Recursion • The case in which a function contains • only a single recursive call and • it is the last statement to be executed in the function. • Tail recursion can be replaced by iteration • to remove recursion from the solution as in the next example. expanded by J. Goetz, 2004

  47. remove recursion • The recursive call causes an activation record to put on the run-time stack to hold the function’s parameters and local variables • Because the recursive call is the last statement in the function, thefunction terminateswithout using these values • So we need to change the “smaller-caller” variable(s) on the recursive call’s parameter list and then “jump” back to the beginning of the function. In other words, we need a loop. C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

  48. // USES TAIL RECURSION bool ValueInList ( ListType list , int value , int startIndex ) // Searches list for value between positions startIndex // and list.length-1 // Pre: list.info[ startIndex ] . . list.info[ list.length - 1 ] // contain values to be searched // Post: Function value = // ( value exists in list.info[ startIndex ] . . list.info[ list.length - 1 ] ) { if ( list.info[startIndex] == value ) // one base case return true ; else if (startIndex == list.length -1 ) // another base case return false ; else // general case return ValueInList( list, value, startIndex + 1 ) ; } 48 expanded by J. Goetz, 2004

  49. // ITERATIVE SOLUTION - it is replaced by iteration //to remove recursion from the solution bool ValueInList ( ListType list , int value , int startIndex ) // Searches list for value between positions startIndex and list.length-1 // Pre: list.info[ startIndex ] . . list.info[ list.length - 1 ] contain values to be searched // Post: Function value = ( value exists in list.info[ startIndex ] . . list.info[ list.length - 1 ] ) /* in the iterative solution: • the base cases become the terminating conditions of the loop • in the generalcase each subsequent execution of the loop body processes a smaller version of the problem; • the unsearched part of the list shrinks with each execution of the loop body because startIndex is incremented */ { bool found = false ; while ( !found && startIndex < list.length ) //it includes bothbase cases {if ( value == list.info[ startIndex ] ) found = true ; else startIndex++ ; // related to thegeneral case } return found ; } 49 expanded by J. Goetz, 2004

  50. Debugging • Put debug output statements during testing • Print out the parameters and local variables, if any, at the beginning and end of the function • Verify that each call attempts to solve a problem smaller than the previous one by printing out the values of the parameters on the recursive call(s) C++ Programming: Program Design Including Data Structures, Second Edition expanded by J. Goetz, 2004

More Related