Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Joe Meehean.  call themselves directly  or indirectly void f(){... f();... } void g(){... h();... } void h(){... g();... }

Similar presentations


Presentation on theme: "1 Joe Meehean.  call themselves directly  or indirectly void f(){... f();... } void g(){... h();... } void h(){... g();... }"— Presentation transcript:

1 1 Joe Meehean

2  call themselves directly  or indirectly void f(){... f();... } void g(){... h();... } void h(){... g();... }

3 int factorial(int x){ int handback; if( x <= 1 ){ handback = 1; }else{ handback = x * factorial(x-1); } return handback; } factorial(4) = 4 * factorial(4 – 1) factorial(3) = 3 * factorial(3 – 1) … factorial(1) = 1

4  When a recursive call is made: marks current place in code clones itself  copy of code  new parameters  new set of uninitialized local variables clone executes starting at beginning  When clone returns clone is cleaned up previous version starts at just after recursive method call

5 CLASS ACTIVITY void doClap(int k){ if(k == 0 ) return; clap k times; doClap(k – 1); return; } 1 st person: doClap(3)

6  doClap(3) 3, 4, 5, 6, … memory access error stack overflow need code to stop recursion eventually void doClap(int k){ clap k times; doClap(k + 1); return; }

7  Must have a base case Condition under which no recursive call is made Helps prevent infinite recursion void doClap(int k){ if( k == 0 ) return; clap k times; doClap(k + 1); return; } Still has infinite recursion?

8  Must make progress towards base case void doClap(int k){ if( k == 0 ) return; clap k times; doClap(k - 1); return; } Does doClap follow rules 1 & 2? Infinite recursion? If so, how should we change the code

9  Must make progress towards base case void doClap(int k){ if( k <= 0 ) return; clap k times; doClap(k - 1); return; } Does doClap follow rules 1 & 2? Infinite recursion? If so, how should we change the code

10  printStr(“hello”, 0) => “hello”  printStr(“hello”, 2) => “llo” void printStr(string s, int k){ if( k >= s.length() ) return; cout << s[k]; printStr(s, k+1); }

11 Design rule assume that all recursive calls work even if you haven’t finished writing it yet void printStr(string s, int k){ if( k >= s.length() ) return; cout << s[k]; printStr(s, k+1); }

12 void printStr(string s, int k){ if( k >= s.length() ) return; cout << s[k] << endl; printStr(s, k+1); } cloneoutput printStr(“hello”, 0) printStr(“hello”, 1) printStr(“hello”, 2) printStr(“hello”, 3) printStr(“hello”, 4) printStr(“hello”, 5) h e l l o

13 void printStr(string s, int k){ if( k >= s.length() ) return; printStr(s, k+1); cout << s[k] << endl; } cloneoutput printStr(“hello”, 0) printStr(“hello”, 1) printStr(“hello”, 2) printStr(“hello”, 3) printStr(“hello”, 4) printStr(“hello”, 5) h e l l o

14  A method may have statements before recursive call after recursive both  After statements are done only when the recursive call is finished and all the recursive calls recursive calls have finished

15  Whats printed for printStr(“STOP”, 0)? void printStr(string s, int k){ if( k >= s.length() ) return; cout << s[k] << endl; printStr(s, k+1); cout << s[k] << endl; }

16  Whats printed for printStr(“STOP”, 0)? STOPPOTS  How can we change it to print STOP POTS void printStr(string s, int k){ if( k >= s.length() ) return; cout << s[k] << endl; printStr(s, k+1); cout << s[k] << endl; }

17  How can we change it to print STOP POTS void printStr(string s, int k){ if( k >= s.length() ){ cout ” << endl; return; } cout << s[k] << endl; printStr(s, k+1); cout << s[k] << endl; }

18 18

19 CallValue of k mystery(3)6 mystery(2)4 mystery(1)2 mystery(0) void mystery(int j){ if( j <= 0 ) return; int k = j * 2; mystery(j – 1); cout << k << “ “; } Each clone gets own local variables Outputs => 2 4 6

20 // sums #s from 1 to max // Iterative version int doSum(int max){ int sum = 0; for(int i = 1; i <= max; i++){ sum += i; } return sum; }

21 // sums #s from 1 to max // Iterative version int doSum(int max){ int sum = 0; for(int i = 1; i <= max; i++){ sum += i; } return sum; } // Recursive version int doSum(int max){ if( max <= 0 ) return 0; return max + doSum(max – 1); }

22 doSum(3) doSum(2) doSum(1) doSum(0) 3 2 1 + + +

23  Can do recursion with int parameters count up or down to base case  Or, with recursive data structures a linked list is either empty or a node followed by a linked list

24  Prints list in order void printList(Node * node){ if( node == NULL ) return; cout data_ << endl; printList(node->next_); }

25  How can we change this code to print list backwards? void printList(Node * node){ if( node == NULL ) return; cout data_ << endl; printList(node->next_); }

26 void printList(Node * node){ if( node == NULL ) return; printList(node->next_); cout data_ << endl; }  Prints list backwards  Rare case where recursion makes code faster as well as simpler

27  Activation records (ARs) stack of ARs maintained at runtime 1 AR for each active method active methods have been called, but not returned yet  Each AR includes: function parameters local variables return address

28  Activation Record Stack when method is called, its AR is pushed when method returns, its AR is popped return address in popped AR tells program where to return control flow

29  Auxiliary recursion wrapper method to do something ONCE before or after recursion OR pass more parameters recursion in auxiliary method wrapper sometimes called a driver  Multiple recursive calls per method need to recurse down a few different paths more on this when we talks about trees

30 // prints a header and the endline // calls aux to print the list void printList(Node * node){ cout << “The list contains: “; printAux(node); cout << endl; } // prints a single string containing // each element in brackets void printAux(Node * node){ if( node == NULL ) return; cout data_ << “]”; printAux(node->next_); }

31 // public method calls private method // with member variable int List::numNodes(){ return numAux(phead_); } // actually counts the nodes int List::numAux(Node * node){ if( node == NULL ){ return 0; } return 1 + numAux(node->next_); }

32  Sum all elements in a vector but the first value int weirdSum(vector & intVect){ return sumVector(intVect, 1); } // actually sums the entries int sumVector( vector & intVect, int pos){ if( pos >= intVect.size() ) return 0; return intVect[pos] + sumAux(intVect, pos + 1); }

33  Fibonacci fib(1) = 1, fib(2) = 1 fib(N) for N > 2 = fib(N-1) + fib(N-2) fib(3) = fib(2) + fib(1) = 1 + 1 = 2 int fib(int n){ if( n <= 2) return 1; return fib(n – 2) + fib(n – 1); }

34 fib(4) fib(3) fib(2) fib(1) + + 11 2 1 3 2  Note: fib(2) is called twice  Redoing work

35  Compound interest rule  Never duplicate work don’t solve the same recursive instance in separate recursive calls repeats work you’ve already done more on how to prevent this in CS242

36 36

37  Recursion DOES NOT make your code faster  Recursion DOES NOT use less memory  Recursion DOES make your code simpler sometimes

38  When you don’t get anything from it?  Tail recursion the only recursive call is the last line local variables stored just to be thrown away  Tail recursion can be replaced with a while loop

39 void printStr(string s, int k){ if( k >= s.length() ) return; cout << s[k] << endl; printStr(s, k+1); } void printStrin(string s, int k){ while( true ){ if( k >= s.length() ) return; cout << s[k] << endl; k = k + 1; }

40 void printString(string s, int k){ while( k < s.length() ){ cout << s[k] << endl; k = k + 1; }

41 1. Base case 2. Make progress 3. Design rule 4. Compound interest rule

42 42


Download ppt "1 Joe Meehean.  call themselves directly  or indirectly void f(){... f();... } void g(){... h();... } void h(){... g();... }"

Similar presentations


Ads by Google