Download presentation
Presentation is loading. Please wait.
Published byJohn Parrish Modified over 9 years ago
1
© Janice Regan, CMPT 128, February. 2007 0 CMPT 128: Introduction to Computing Science for Engineering Students Recursion
2
© Janice Regan, CMPT 128,2007-2013 1 Introduction to Recursion Recursion: A function that calls itself is said to be a recursive function A function that calls itself results in direct recursion If function A calls function B, and in turn function B calls function A this results in indirect recursion C++, like most high-level languages, allows recursion Recursion can result in elegant easy to understand and develop code (‘efficient’ development and maintenance) Recursion may be less ‘efficient’ to execute than an equivalent iterative solution,
3
© Janice Regan, CMPT 128,2007-2013 2 Recursive void Functions Recursion is based on the design technique know as ‘divide and conquer’ Divide: break the task into smaller parts Conquer: solve a large and complex problem efficiently When solving a problem recursively Divide: each smaller part of the task is the same as the whole task The same algorithm or series of steps is used for the whole problem and for each smaller task the problem is divided into
4
© Janice Regan, CMPT 128,2007-2013 3 Example: quick sort Consider large task: sort a large array into descending order Choose pivot from ‘middle’ of array, Switch the pivot and first element in array Sort the array into two parts, one with all numbers larger than the pivot, one with all numbers smaller than the pivot Move the pivot back between the two parts Subtasks must be smaller versions of original task Subtask 1: repeat the main task on the part of the array with elements larger than the pivot Subtask 2: repeat the main task on the part of the array with elements smaller than the pivot. Quick sort is a method of the type that is well suited to be solved by recursion
5
© Janice Regan, CMPT 128,2007-2013 4 Recursive void Function: a simple example Task: calculate the sum of the squares of all integers from 1 to j, for all integers j from 1 to n. Display sums of integers vertically, one line for each j, beginning with j=1 Example call: sumSqIntegers(4); Produces output: 1 5 14 30
6
© Janice Regan, CMPT 128,2007-2013 5 Sums of squares: Recursive Definition Break problem into two cases Base case: if n=1 Simply write number n to screen (1*1=1) Do not call the function again Return to the calling function (previous recursive call) Recursive case: if n>1, two subtasks: Calculate and print all sums for j=1,..,n-1 Calculate and print the sum for j=n Return to the calling function
7
© Janice Regan, CMPT 128,2007-2013 6 Sums of squares: Recursive Definition Example: argument 4: 1 st subtask calculates the sums for each j j=1,…,3 and prints them one per line 1, 5, 14 Call the function sumSqIntegers for j-1 2 nd subtask calculates the sum for j=4 and prints it on a new line, 30 Return to the calling program
8
© Janice Regan, CMPT 128,2007-2013 7 sumSqIntegers: Function Definition void sumSqIntegers(int maxInteger, int& value) { if (maxInteger == 1) { cout << maxInteger << endl; //Base case value = maxInteger; } else { sumSqIntegers(maxInteger-1, value); value += maxInteger * maxInteger; //Recursive case cout << value << endl;}
9
© Janice Regan, CMPT 128,2007-2013 8 Sums of squares: Trace (1) Example call: sumSqIntegers(4,value); //1 st call sumSqIntegers(3,value); //2 nd call sumSqIntegers(2,value); //3 rd call sumSqIntegers(1,value); //4 th call cout << 1 << endl; //4 th call cout << 2*2 + 1 << endl; //3 rd call cout << 3*3 + 5 << endl; //2 nd call cout << 4*4 +14 << endl; //1 st call
10
© Janice Regan, CMPT 128,2007-2013 9 Sums of squares: Trace (2) During 1 st call n=4, and the function is called for n=3 (recursive case) During 2 nd call n=3, and the function is called for n=2 (recursive case) During 3 rd call n=2, and the function is called for n=1 (recursive case) During 4 th call n=1, 1is printed to the screen and the cursor moves to the next line (stopping case) then returns to 3 rd case During the remainder of the 3 rd call n=2, 5 is printed to the screen and the cursor moves to the next line (completes recursive case) then returns to 2 nd case During the remainder of the 2 nd call n=3, 14 is printed to the screen and the cursor moves to the next line (completes recursive case) then returns to 1 st case During the remainder of the 1 st call n=4, 30 is printed to the screen and the cursor moves to the next line (completes recursive case) then returns to calling program
11
© Janice Regan, CMPT 128,2007-2013 10 Sums of squares: Trace (3) void sumSqIntegers(int maxInteger, int& value) { if (maxInteger == 1) { //Base case cout << maxInteger << endl; value = maxInteger; } else { //Recursive case sumSqIntegers(maxInteger-1, value); value += maxInteger * maxInteger; cout << value << endl;} 3 rd call: sumSqIntegers(1, value) 4 th call: Print 1, value=1 Calling function: sumSqIntegers(4, value) 1 st call: sumSqIntegers(3, value) 2 nd call: sumSqIntegers(2, value)
12
© Janice Regan, CMPT 128,2007-2013 11 Sums of squares: Trace (4) Calling function: sumSqIntegers(4, value) 1 st call: sumSqIntegers(3, value) 2 nd call: sumSqIntegers(2, value) 3 rd call: determine value value = 1+2*2 Print 5 void sumSqIntegers(int maxInteger, int& value) { if (maxInteger == 1) { //Base case cout << maxInteger << endl; value = maxInteger; } else { //Recursive case sumSqIntegers(maxInteger-1, value); value += maxInteger * maxInteger; cout << value << endl;}
13
© Janice Regan, CMPT 128,2007-2013 12 Sums of squares: Trace (5) Calling function: sumSqIntegers(4, value) 1 st call: sumSqIntegers(3, value) void sumSqIntegers(int maxInteger, int& value) { if (maxInteger == 1) { //Base case cout << maxInteger << endl; value = maxInteger; } else { //Recursive case sumSqIntegers(maxInteger-1, value); value += maxInteger * maxInteger; cout << value << endl;} 2 nd call: determine value value = 5 + 3*3 Print 14
14
© Janice Regan, CMPT 128,2007-2013 13 Sums of squares: Trace (6) Calling function: sumSqIntegers(4, value) void sumSqIntegers(int maxInteger, int& value) { if (maxInteger == 1) { //Base case cout << maxInteger << endl; value = maxInteger; } else { //Recursive case sumSqIntegers(maxInteger-1, value); value += maxInteger * maxInteger; cout << value << endl;} 1 st call: determine value value = 14+4*4 Print 30
15
© Janice Regan, CMPT 128,2007-2013 14 Infinite Recursion Base case MUST eventually be entered If there is no base case OR If the base case is never reached Then recursion continues for ever (or at least until memory for new function frames is exhausted) In our example (sumSqIntegers): Base case happened when we reached 1, the sum of the squares of integers 1,..,1 is 1 That’s when recursion stopped and we began returning up through the stack of recursive frames
16
© Janice Regan, CMPT 128,2007-2013 15 Infinite Recursion: Example Consider alternate function definition: void altSumSqIntegers(int maxInteger, int& value) { altsumSqIntegers(maxInteger-1, value); value += maxInteger * maxInteger; cout << value << endl; } Seems logical on the surface but there is no stopping case so recursion never stops
17
© Janice Regan, CMPT 128,2007-2013 16 Recursion: Review A recursive function must have: One or more recursive cases where the function accomplishes it’s task by: Making one or more recursive calls to solve smaller versions of original task One or more base cases or stopping cases where the function accomplishes it’s task by simple calculation without recursive call
18
© Janice Regan, CMPT 128,2007-2013 17 Stacks for Recursion A stack Specialized memory structure Like stack of paper Place each new page (frame) on top When you finish with one page (frame) then take the page (frame) from the top of the stack and continue Called "last-in/first-out“ (LIFO) memory structure Recursion uses stacks Each recursive call placed on stack When one completes, last call is removed from stack
19
© Janice Regan, CMPT 128,2007-2013 18 Stack Overflow Size of stack limited Memory is finite Long chain of recursive calls continually adds to stack All are added before base case causes removals If stack attempts to grow beyond limit: Stack overflow error Infinite recursion always causes this
20
© Janice Regan, CMPT 128,2007-2013 19 Why Use Recursion Recursion is not always the ‘best solution’ Some languages do not allow recursion Any task accomplished with recursion can also be done using iteration Recursive: Recursion can result in elegant easy to understand and develop code (‘efficient’ development and maintenance) Recursion may be less ‘efficient’ to execute than an equivalent iterative solution (may run slower)
21
© Janice Regan, CMPT 128,2007-2013 20 Recursive Functions can have any type Recursion not limited to void functions Can return value of any type Same approach as for our original example Let’s recast that original example so that the recursive function has type int rather than type void
22
© Janice Regan, CMPT 128,2007-2013 21 sumSqIntegers: Function Definition int sumSqIntegers(int maxInteger) { int value; if (maxInteger == 1) { cout << maxInteger << endl; //Base case return(maxInteger); } else { sumSqIntegers(maxInteger-1); value += maxInteger * maxInteger; //Recursive case cout << value << endl; return(value);}
23
© Janice Regan, CMPT 128,2007-2013 22 Sums of squares: Trace (1) Example call: sumSqIntegers(4); //1 st call sumSqIntegers(3); //2 nd call sumSqIntegers(2); //3 rd call sumSqIntegers(1); //4 th call cout << 1 << endl; //4 th call cout << 2*2 + 1 << endl; //3 rd call cout << 3*3 + 5 << endl; //2 nd call cout << 4*4 +14 << endl; //1 st call
24
© Janice Regan, CMPT 128,2007-2013 23 Return a Value Recursion Example: Powers Recall predefined function pow(): result = pow(2.0,3.0); Returns 2 raised to power 3 (8.0) Takes two double arguments Returns double value Let’s write recursively For simple example
25
© Janice Regan, CMPT 128,2007-2013 24 Function Definition for power() int power(int x, int n) { if (n 0) { return (power(x, n-1)*x); } else { return (1); } }
26
© Janice Regan, CMPT 128,2007-2013 25 Calling Function power() Larger example: power(2,3); power(2,2)*2 power(2,1)*2 power(2,0)*2 1 Reaches base case Recursion stops Values "returned back" up stack
27
© Janice Regan, CMPT 128,2007-2013 26 Recursive Design Techniques Start simple Make sure the problem can be broken into parts that are copies of each other and the ‘whole’ problem Define your recursive cases Do the recursive cases return or produce the correct results Define your stopping case or cases When will the series of recursive calls end Do the stopping cases return or produce the correct results Make sure that you stop your recursive case and enter the stopping cases when conditions are correct
28
© Janice Regan, CMPT 128,2007-2013 27 Recursive design: power Consider power() again Can the problem be broken down into smaller parts: x n = x i *x k where n=i+k this problem can be broken down into parts that are equivalent to the ‘whole’ problem Design the recursive case power(x, n) returns: power(x, n – 1) * x Is this correct? x n = x n-1 *x so yes Design the stopping case x 0 =1, x 1 =x When do we stop? When n=0 we know the answer regardless of the value of x So out stopping case is n=0, x 0 =1
29
© Janice Regan, CMPT 128,2007-2013 28 Recursive Design Check: power() Can infinite recursion happen with the power() function we have designed 2 nd argument decreases by 1 each call Eventually we will reach the base case of n=0 Does the stopping case return the correct value: n=0 is base case which implies power(x,0) power(x,0) returns 1, which is correct for x 0 Does the recursive case return the correct value: For n>1, power(x,n) returns power(x,n-1)*x x n = x n-1 *x so this is correct
30
© Janice Regan, CMPT 128,2007-2013 29 Another recursive example Now lets return to our discussion of quick sort and see the application of recursion to that algorithm
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.