Loading in 2 Seconds...

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

Loading in 2 Seconds...

100 Views

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. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -

**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 • 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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**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**// 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**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**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**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**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**//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**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**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**C++ Programming: Program Design Including Data Structures,**Second Edition expanded by J. Goetz, 2004**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**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**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**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**// 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**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**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**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**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**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**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**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**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**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**// 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**// 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**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