Presentation is loading. Please wait.

Presentation is loading. Please wait.

Introduction to Computer Science Recursion The Runtime Stack Unit 15.

Similar presentations


Presentation on theme: "Introduction to Computer Science Recursion The Runtime Stack Unit 15."— Presentation transcript:

1 Introduction to Computer Science Recursion The Runtime Stack Unit 15

2 15- 2 Recursion A method that calls itself is said to be recursive (Another formulation: A message that causes itself to be sent as another message) We have been looking a lot at loops: for, while, and do-while loops; recursion can be used as a substitute for loops, but it can do much more The ability to use recursion gives Java a lot of power, and gives us a new way of thinking about problem solutions

3 15- 3 Loop Example: Count Digits in “number” numberOfDigits = 0; rest = number; do { // The number of digits in number is // numberOfDigits plus the remaining // digits in rest rest = rest / 10; numberOfDigits++; } while (rest != 0);

4 15- 4 Recursion Example: Count Digits in “number” Definition of digits(n) : 1 if -9  n  9, digits( n ) = 1 + digits(n/10) otherwise. {

5 15- 5 Recursion Example: Count Digits in “number” 1if -9  n  9, digits( n ) = 1 + digits(n/10)otherwise. { digits(321)= 1 + digits(321/10) = 1 + digits(32) = 1 + (1 + digits(32/10)) = 1 + (1 + digits(3)) = 1 + (1 + (1)) = 3

6 15- 6 Recursive Definition A definition that is self-referential A definition that is defined in terms of simpler instances of itself It is not a “circular definition”; that would lead nowhere It is a “spiraling definition” that eventually terminates, and that must include a “base case”, a final part of the definition that does not call itself

7 15- 7 Recursion Example: Count Digits in “number” int numberOfDigits(int n) { if ( (-10 < n) && (n < 10) ) return 1; else return (1 + numberOfDigits(n/10)); }

8 15- 8 How to Write a Recursive Function, f(x) If you want to compute f(x), but can’t do it directly 1. Assume you can compute f(y), for all values y smaller than x 2. Define f(x) in terms of f(y) 3. Define the base case(s) — define f(x) directly (i.e., not in terms of f(y)) for some base value(s) of x

9 15- 9 Counting Digits Recursively, Again int numberOfDigits(int n) { if ( (-10 < n) && (n < 10) ) return 1; else return (1 + numberOfDigits(n/10)); } f(x)

10 15- 10 Counting Digits Recursively, Again int numberOfDigits(int n) { if ( (-10 < n) && (n < 10) ) return 1; else return (1 + numberOfDigits(n/10)); } 1. We assume we can compute f(y) for y smaller than x f(x)

11 15- 11 Counting Digits Recursively, Again int numberOfDigits(int n) { if ( (-10 < n) && (n < 10) ) return 1; else return (1 + numberOfDigits(n/10)); } 2. f(x) defined in terms of f(y), where y is smaller than x 1. We assume we can compute f(y) for y smaller than x f(x)

12 15- 12 Counting Digits Recursively, Again int numberOfDigits(int n) { if ( (-10 < n) && (n < 10) ) return 1; else return (1 + numberOfDigits(n/10)); } 2. f(x) defined in terms of f(y), where y is smaller than x 1. We assume we can compute f(y) for y smaller than x f(x) 3. Define the base case for some x not in terms of f(y)

13 15- 13 Another Example: factorial int factorial(int n) { // Recursively multiply positive numbers // 1 through n if ( (n == 0) || (n == 1) ) return 1; else return ( n * factorial(n - 1) ); }

14 15- 14 Another Example: factorial int factorial(int n) { // Recursively multiply positive numbers // 1 through n if ( (n == 0) || (n == 1) ) return 1; else return ( n * factorial(n - 1) ); } f(x)

15 15- 15 Another Example: factorial int factorial(int n) { // Recursively multiply positive numbers // 1 through n if ( (n == 0) || (n == 1) ) return 1; else return ( n * factorial(n - 1) ); } 1. We assume we can compute f(y) for y smaller than x f(x)

16 15- 16 Another Example: factorial int factorial(int n) { // Recursively multiply positive numbers // 1 through n if ( (n == 0) || (n == 1) ) return 1; else return ( n * factorial(n - 1) ); } 2. f(x) defined in terms of f(y), where y is smaller than x 1. We assume we can compute f(y) for y smaller than x f(x)

17 15- 17 Another Example: factorial int factorial(int n) { // Recursively multiply positive numbers // 1 through n if ( (n == 0) || (n == 1) ) return 1; else return ( n * factorial(n - 1) ); } 2. f(x) defined in terms of f(y), where y is smaller than x 1. We assume we can compute f(y) for y smaller than x f(x) 3. Define the base case for some x not in terms of f(y)

18 15- 18 So What’s Wrong with This? Recursive Definition of power( ) int power(int k,// number to be raised int n) {// power to which to raise return ( k * power(k, n-1) ); } Compute k n Right — missing the base case definition; this will go around in circles

19 15- 19 Recursive Definition of power( ) int power(int k,// number to be raised int n) {// power to which to raise if (n == 0) return 1; else return ( k * power(k, n-1) ); }

20 15- 20 Recursive Definition of power( ) int power(int k,// number to be raised int n) {// power to which to raise if (n == 0) return 1; else return ( k * power(k, n-1) ); } f(x)

21 15- 21 Recursive Definition of power( ) int power(int k,// number to be raised int n) {// power to which to raise if (n == 0) return 1; else return ( k * power(k, n-1) ); } f(x) 1. We assume we can compute f(y) for y smaller than x

22 15- 22 Recursive Definition of power( ) int power(int k,// number to be raised int n) {// power to which to raise if (n == 0) return 1; else return ( k * power(k, n-1) ); } f(x) 1. We assume we can compute f(y) for y smaller than x 2. f(x) defined in terms of f(y), where y is smaller than x

23 15- 23 Recursive Definition of power( ) int power(int k,// number to be raised int n) {// power to which to raise if (n == 0) return 1; else return ( k * power(k, n-1) ); } f(x) 1. We assume we can compute f(y) for y smaller than x 2. f(x) defined in terms of f(y), where y is smaller than x 3. Define the base case for some x not in terms of f(y)

24 15- 24 What’s the Point? We could write power( ) iteratively: int power(int k, int n) { int result = 1; while (n > 0) { result = result * k; n--; } return result; }

25 15- 25 Recursion Can Do Better Recursion does add overhead to a calculation Sometimes it is no better (or even worse) than iteration But recursion can also be better:  Recursion can give us a solution where iteration would be much harder to define  It can open up superior, more efficient solutions, for us

26 15- 26 New Definition of power( ) Consider a better, more efficient definition of power( ):  If n is even, then k n is equal to (k (n/2) ) 2  If n is odd, then k n is equal to k*(k ((n-1)/2) ) 2 This leads to a divide and conquer algorithm; the method makes use of a problem half the size of the original

27 15- 27 New Definition of power( ) int power(int k,// number to be raised int n) {// power to which to raise if (n == 0) return 1; else { int t = power(k, n/2); if ( (n % 2) == 0 ) return (t * t); //n is even else return ( k * t * t ); //n is odd } }

28 15- 28 A Few Points on power( ) t = power(k, n/2) works because integer division gives us n/2 if n is even, and (n-1)/2 if n is odd (just what we wanted) The first version of power( ) uses n multiplications to calculate the answer This version of power( ) uses log 2 n multiplications, a much smaller number Again, recursion is not always more efficient But recursion made the second version natural

29 15- 29 Sometimes, the Recursive Call Appears More than Once A recursive method can call itself multiple times It works the same way:  Assume the recursive calls work  Define the function in terms of the recursive calls  Define the base case

30 15- 30 Another example: Fibonacci if n is 1 or 2, the nth Fibonacci number is 1 if n is 3 or more, the nth Fibonacci number is the sum of the previous two Fibonacci numbers Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144…

31 15- 31 The Recursive fibonacci( ) Definition int fibonacci (int n) { // Recursively calculates Fibonacci number if ( (n == 1) || (n == 2) ) return 1; else return ( fibonacci(n – 1) + fibonacci(n – 2) ); } 2. f(x) defined in terms of f(y), where y is smaller than x

32 15- 32 Another Example: recursive definition of choose( ) function Compute binomial coefficients, “n choose k”, i.e., ( ) Given a set S of n distinct objects, for n ≥ 1, and a number 0 ≤  k ≤  n, how many subsets of S have exactly k elements? Example: Set S = {1, 2, 3}, k = 2; how many subsets of S have exactly 2 elements? “3 choose 2” is 3 (that is, {1, 2}, {1, 3}, {2, 3} ). n k

33 15- 33 Recursion to the Rescue The solution would be much more difficult without recursion Assume we can calculate the function choose( ) for any values smaller than n and k Now define choose( ) in terms of choose( ) over smaller n’s and k’s…

34 15- 34 Pick out one element of S; call it a Every subset of S either includes a or it doesn't We can count the subsets by counting those with a, and counting those without a, and adding them up A k-element subset containing a is formed by choosing k - 1 elements from the remaining n - 1 elements of S, so there are ( ) such subsets A k-element subset that excludes a is formed by choosing k elements from the remaining n - 1 elements of S, so there are ( ) such subsets n - 1 k - 1 n - 1 k

35 15- 35 Specific Example S = {1, 2, 3}, n = 3; k = 2; how many subsets of S have exactly 2 elements? “3 choose 2” is three (that is, {1, 2}, {1, 3}, {2, 3} ) All these sets either include “1” or they don’t Notice:  Two of the sets include “1”: {1, 2} and {1, 3}  One of the sets doesn’t include “1”: {2, 3}

36 15- 36 Specific Example, continued We can figure out how many sets include “1” by pretending S is {2, 3}, and looking at “n-1 choose k-1” (that is, “2 choose 1’): There are two such sets: {2} and {3} These correspond to the “n choose k” (that is, “3 choose 2”) sets that include “1”, namely {1, 2} and {1, 3}

37 15- 37 Specific Example, continued We can figure out how many sets do not include “1” by pretending S is {2, 3}, and looking at “n - 1 choose k” (that is, “2 choose 2”): There is one such set: {2, 3} This corresponds to the “n choose k” (that is, “3 choose 2”) set that doesn't include “1”, namely {2, 3}

38 15- 38 Specific Example, finished Add up the number of sets that do include “1” (there are two) with the number of sets that do not include “1” (there is one), and you get the final answer: three “3 choose 2” defined in terms of  “2 choose 1” and  “2 choose 2” “n choose k” defined in terms of  “n – 1 choose k – 1” and  “n – 1 choose k”

39 15- 39 So Far, So Good But we are not done What about the base case(s)? int choose(int n, int k) { return ( choose(n-1, k-1) + choose(n-1, k) ); }

40 15- 40 The Base Cases It turns out that only two base cases are required, when k is 1, and when k is n When k is 1, then ( ) is n, because there are n 1-element subsets of an n- element set When k is n, then ( ) is 1, because there is 1 n-element subset of an n- element set n k n k

41 15- 41 Recursive Definition of choose( ) int choose(int n, int k) { if (k == 1) return n; else if (k == n) return 1; else return ( choose(n-1, k-1) + choose(n-1, k) ); }

42 15- 42 What’s Happening in the Computer? The runtime stack, which plays an important role when one method sends a message to an object, is important for understanding what’s happening with recursion, too A brief review…

43 15- 43 A Stack Handles Nesting Let’s improve the way we think about this nesting When method e calls method f( ), which calls method g( ), we can think of a “stack of methods” Like putting a piece of paper on top of another piece on top of another piece... the topmost piece is the method being executed now, the others we’ll return to Each piece of paper holds the parameters and local variables

44 15- 44 Starting Execution in main( ) Method main( ) STACK public static void main (String[ ] args) {......... obj.e();... } top

45 15- 45 Call to method e( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK void e ( ) {...... obj.f( );... } public static void main (String[ ] args) {......... obj.e();... } top

46 15- 46 Executing method e( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK void e ( ) {...... obj.f( );... } public static void main (String[ ] args) {......... obj.e();... } top

47 15- 47 Call to method f( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } top

48 15- 48 Executing method f( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } top

49 15- 49 Call to method g( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 Method g( ) Where we came from: f, line 4 top void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... }

50 15- 50 Method g( ) finishes, the stack has its top removed void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... } Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 top

51 15- 51 Method f( ) finishes, the stack has its top removed void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... } Method e( ) Where we came from: main, line 4 Method main( ) STACK top

52 15- 52 Method e( ) finishes, the stack has its top removed void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... } Method main( ) STACK top

53 15- 53 Variables are held on the stack, too When we put items on the stack, we also write down  values of parameters  local variables Now, let’s look at a recursive example, namely power( ) The runtime stack keeps track of where we came from and where we’ll return to

54 15- 54 Call to power(7, 5) from main( ) public static void main (String[ ] args) { … int x = power(7, 5); … }

55 15- 55 A reminder of power( ); parameters k and n; local variable t int power(int k,// number to be raised int n) {// power to which to raise if (n == 0) return 1; else { int t = power(k, n/2); if ( (n % 2) == 0 ) return (t * t); else return ( k * t * t ); } }

56 15- 56 Delayed Evaluation The recursive call to a method leaves partially evaluated expressions on the stack The recursive call typically occurs while an expression is being calculated. The stack delays the expression’s evaluation In this case, we’ll delay the evaluation of t = power(k, n/2);

57 15- 57 The Runtime Stack (recursion) Method power( ) Where we came from: main, line … k: 7 n: 5 t: uninitialized Method main( ) STACK top

58 15- 58 The Runtime Stack (recursion) Method power( ) Where we came from: main, line … k: 7 n: 5 t: uninitialized Method main( ) STACK top Method power( ) Where we came from: power, line 6 k: 7 n: 2 t: uninitialized

59 Method power( ) Where we came from: main, line … k: 7 n: 5 t: uninitialized Method main( ) STACK top Method power( ) Where we came from: power, line 6 k: 7 n: 2 t: uninitialized Method power( ) Where we came from: power, line 6 k: 7 n: 1 t: uninitialized

60 Method power( ) Where we came from: main, line … k: 7 n: 5 t: uninitialized Method main( ) top Method power( ) Where we came from: power, line 6 k: 7 n: 2 t: uninitialized Method power( ) Where we came from: power, line 6 k: 7 n: 1 t: uninitialized Method power( ) Where we came from: power, line 6 k: 7 n: 0 t: uninitialized

61 15- 61 n equal to zero causes power( ) to return 1, and sets t to returned value Method power( ) Where we came from: main, line … k: 7 n: 5 t: uninitialized Method main( ) Method power( ) Where we came from: power, line 6 k: 7 n: 2 t: uninitialized Method power( ) Where we came from: power, line 6 k: 7 n: 1 t: 1 top

62 15- 62 Returning to power( ), line 7, we return k*t*t (i.e., 7) from line 10 Method power( ) Where we came from: main, line … k: 7 n: 5 t: uninitialized Method main( ) Method power( ) Where we came from: power, line 6 k: 7 n: 2 t: 7 top STACK

63 15- 63 The value of n is 2, n%2 is 0, and we return t*t (i.e., 49) from line 8 Method power( ) Where we came from: main, line … k: 7 n: 5 t: 49 Method main( ) top STACK

64 15- 64 Finally, power( ) sees that n is 5, n%2 is 1, and it returns k*t*t to main Method main( ) top STACK main( ) gets value 16,807

65 15- 65 What You’ve Seen, Recursively-speaking Simple recursive functions, f( )  numberOfDigits(n), uses 1 + f(n/10)  factorial(n), uses n * f(n - 1)  power(k, n), uses n * f(k, n - 1)  Then a better power(k, n), using a divide and conquer approach  fibonacci(n), using f(n - 1) + f(n - 2)  choose(n, k), using f(n - 1, k - 1) + f(n - 1, k) The runtime stack for power(k, n)

66 15- 66 Another Example of Delayed Evaluation int sum (int n) { // Use recursion for addition of positive numbers. // Recursion is *not* the best way to do this… // It's just an example of delayed evaluation if (n == 1) return 1; else return ( n + sum(n - 1) ); }

67 15- 67 Let’s say n is 5 Sum = 5 + Sum (5 – 1) // first Sum = 4 + Sum (4 – 1) // second Sum = 3 + Sum (3 – 1) // third Sum = 2 + Sum (2 – 1) //fourth Sum = 1 // fifth Sum = 2 + 1 // fourth Sum = 3 + 3 // third Sum = 4 + 6 // second Sum = 5 + 10 // first return ( n + sum(n – 1) ) // unless n is 1

68 15- 68 Leaving Statements to be Executed Sometimes, as with power( ), there are statements left to execute in the recursive function, after the call to the next copy of itself is finished With power( ), after t got its value, there was still a calculation to be carried out before another value was returned Here’s another example…

69 15- 69 Print a Sentence in Reverse class Recur { // Uses recursion to read a line and echo it in reverse static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); // The recursive call System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a ” + “palindrome.”); stackTheCharacters( );//The first call System.out.println( ); } } //Recur

70 How does it work? When stackTheCharacters( ) is called, it reads a character value for its local variable theCharacter stackTheCharacters( ) is then called again, so… The final statement of the first call, that is System.out.print(theCharacter), is still waiting when the second call to stackTheCharacters( ) reads the next character Eventually we get back to finish the first call, and print theCharacter Enter a sentence that is not a palindrome. Was that a Toyota I saw? ?was I atoyoT a taht saW theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter);

71 The Role of the Runtime Stack The Runtime Stack Was that a Toyota I saw? class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

72 Remember where we are in main( ) Was that a Toyota I saw? System.out.println( ) The Runtime Stack theCharacter is ??? class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

73 About to call stackTheCharacters( ) Was that a Toyota I saw? System.out.println( ) The Runtime Stack theCharacter is ‘W’ class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

74 Called stackTheCharacters( ) (again) The Runtime Stack Was that a Toyota I saw? Syst...(theCharacter) theCharacter is ‘W’ theCharacter is ??? System.out.println( ) class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

75 The Runtime Stack Was that a Toyota I saw? Called stackTheCharacters( ) (again 2 ) Syst...(theCharacter) theCharacter is ‘W’ theCharacter is ??? Syst...(theCharacter) theCharacter is ‘a’ System.out.println( ) class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

76 The Runtime Stack Was that a Toyota I saw? Called stackTheCharacters( ) (again 3 ) Syst...(theCharacter) theCharacter is ‘W’ theCharacter is ??? Syst...(theCharacter) theCharacter is ‘a’ Syst...(theCharacter) theCharacter is ‘s’ System.out.println( ) class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

77 The Runtime Stack Was that a Toyota I saw? Called stackTheCharacters( ) (again 24 )...... Syst...(theCharacter) theCharacter is ‘W’ theCharacter is ??? Syst...(theCharacter) theCharacter is ‘a’ Syst...(theCharacter) theCharacter is ‘w’ System.out.println( ) class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

78 The Runtime Stack Was that a Toyota I saw? Print ‘?’, then finish executing the 23 interrupted instances of stackTheCharacters( )...... Syst...(theCharacter) theCharacter is ‘W’ theCharacter is ‘?’ Syst...(theCharacter) theCharacter is ‘a’ Syst...(theCharacter) theCharacter is ‘w’ System.out.println( ) class Recur { static void stackTheCharacters( ) { char theCharacter; SimpleInput sinp = new SimpleInput(System.in); theCharacter = sinp.readChar( ); if (!sinp.eoln( )) stackTheCharacters( ); System.out.print(theCharacter); }// stackTheCharacters public static void main (String[ ] args) { System.out.println(“Enter a sentence that is not a palindrome.”); stackTheCharacters( ); System.out.println( ); }

79 Completing the (Interrupted) Methods (then System.out.println of the main block) theCharacter is ‘?’ and we execute System.out.print(‘?’) Was that a Toyota I saw? ? theCharacter becomes ‘w’ and execute System.out.print(‘w’) ?w theCharacter becomes ‘a’ and execute System.out.print(‘a’) ?wa theCharacter becomes ‘W’ and execute System.out.print(‘W’) ?was I atoyoT a taht saW......

80 The Runtime Stack class Recur { static void stackTheCharacters24( ) { theCharacter = sinp.readChar( ); System.out.print(theCharacter); } static void stackTheCharacters3( ) { theCharacter = sinp.readChar( ); stackTheCharacters4( ); System.out.print(theCharacter); } static void stackTheCharacters2( ) { theCharacter = sinp.readChar( ); stackTheCharacters3( ); System.out.print(theCharacter); } static void stackTheCharacters1( ) { theCharacter = sinp.readChar( ); stackTheCharacters2( ); System.out.print(theCharacter); } public static void main(String[ ] args) { System.out.println (“Enter a sentence that is not a palindrome.”); stackTheCharacters1( ); System.out.println( ); } } // Recur Was that a Toyota I saw? An “unfolded” way of looking at those 24 calls of stackTheCharacters( ) stackTheCharacters1 main stackTheCharacters2 stackTheCharacters3........ Syst...(theCharacter) theCharacter is ‘W’ System.out.println( ) theCharacter is ‘?’ Syst...(theCharacter) theCharacter is ‘a’ Syst...(theCharacter) theCharacter is ‘s’ stackTheCharacters24

81 The “unfolded” statements that are executed System.out.println("Please enter a sentence."); theCharacter =sinp.readChar( ); //Reading in 'W' theCharacter = sinp.readChar( ); // Reading in 'a' t heCharacter = sinp.readChar( ); // Reading in 's' theCharacter = sinp.readChar( ); // Reading in ' ' theCharacter = sinp.readChar( ); // Reading in 't'..... // intermediate calls theCharacter = sinp.readChar( ); // Reading in 'w' theCharacter = sinp.readChar( ); // Reading in '?' System.out.print(theCharacter); // Printing the '?' System.out.print(theCharacter); // Printing the 'w'..... // intermediate calls System.out.print(theCharacter); // Printing the 't' System.out.print(theCharacter); // Printing the ' ' System.out.print(theCharacter); // Printing the 's' System.out.print(theCharacter); // Printing the 'a' System.out.print(theCharacter); // Printing the 'W' System.out.println( ); // Last statement in main

82 15- 82 Tail Recursion With tail, or end, recursion, there is nothing left to do after the last call. No unfinished statements have been left on the stack. (The previous example, stackTheCharacters( ), was not an example of tail recursion because the System.out.print( ) call remained to be executed in each copy after the recursive call finished.)

83 15- 83 Specify the Recursive Procedure like a Loop Goal: Print a positive integer in reverse. Stacking Plan: Print the ‘ones’ digit. Bound: There are no more digits to print. Unstacking Plan: — Later we’ll see another example where the Unstacking Plan is not empty.

84 15- 84 An Example of Tail Recursion Class unDigit { // Recursively reverses the digits of a positive integer static void reverseDigits(int number) { System.out.print(number % 10); if ( (number / 10) != 0 ) reverseDigits(number/10); } public static void main (String[ ] args) { int num; SimpleInput sinp = new SimpleInput(System.in); System.out.print("Please enter positive integer."); num = sinp.readInt( ); reverseDigits(num); System.out.println( ); }

85 15- 85 Tail Recursion is easily re-written as an iterative loop void iterativeReverse(int theNumber) { do { System.out.print(theNumber % 10); theNumber = theNumber / 10; } while (theNumber != 0) ; } Please enter a positive integer. 26407 70462

86 15- 86 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

87 15- 87 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

88 15- 88 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

89 15- 89 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

90 15- 90 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

91 15- 91 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

92 15- 92 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

93 15- 93 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

94 15- 94 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

95 15- 95 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

96 15- 96 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

97 15- 97 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

98 15- 98 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

99 15- 99 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

100 15- 100 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

101 15- 101 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

102 15- 102 The Towers of Hanoi Move the entire stack from peg A to peg C, while obeying two rules: 1. Only one disk can be moved at a time. 2. A larger disk can never go on top of a smaller one. Peg APeg BPeg C

103 15- 103 The Recursive Solution 1. Move n – 1 disks from A to B. 2. Move 1 disk from A to C. 3. Move n – 1 disks from B to C. Peg APeg BPeg C

104 15- 104 The Recursive Solution 1. Move n – 1 disks from A to B. 2. Move 1 disk from A to C. 3. Move n – 1 disks from B to C. Peg APeg BPeg C

105 15- 105 The Recursive Solution 1. Move n – 1 disks from A to B. 2. Move 1 disk from A to C. 3. Move n – 1 disks from B to C. Peg APeg BPeg C

106 15- 106 The Recursive Solution 1. Move n – 1 disks from A to B. 2. Move 1 disk from A to C. 3. Move n – 1 disks from B to C. Peg APeg BPeg C

107 15- 107 The Recursive Solution 1. Move n – 1 disks from A to B. 2. Move 1 disk from A to C. 3. Move n – 1 disks from B to C. Peg APeg BPeg C

108 15- 108 The Recursive Solution 1. Move n – 1 disks from A to B. 2. Move 1 disk from A to C. 3. Move n – 1 disks from B to C. Peg APeg BPeg C

109 15- 109 The Recursive Solution 1. Move n – 1 disks from A to B. 2. Move 1 disk from A to C. 3. Move n – 1 disks from B to C. Peg APeg BPeg C

110 15- 110 The Recursive Specification Goal: Solve the Tower of Hanoi problem for height n. Stacking plan: Move n – 1 disks from fromPeg to usingPeg. Bound: There’s just one disk left (it goes from fromPeg to toPeg). Unstacking plan: Move n – 1 disks from usingPeg to toPeg. We use the “other” peg as a temporary holder, and that peg’s identity keeps changing — so we’ll use fromPeg, toPeg, and usingPeg instead of A, B, C.

111 15- 111 The Java Method static void move (int height, int fromPeg, int toPeg, int usingPeg) { // Recursive procedure for determining moves. // Keep this order—from, to, using—in mind when you // read the recursive calls. if ( height == 1 ) System.out.println("Move a disk from " + fromPeg + " to " + toPeg); else { move(height – 1, fromPeg, usingPeg, toPeg); System.out.println("Move a disk from " + fromPeg +" to " + toPeg); move(height – 1, usingPeg, toPeg, fromPeg); } }

112 15- 112 The Java Class class Hanoi { static void move(int height, int fromPeg, int toPeg, int usingPeg) {…} public static void main (String[ ] args) { int height; SimpleInput sinp=new SimpleInput(System.in); System.out.print("How many disks are you" + “ going to start with? "); height = sinp.readInt( ); move(height, 1, 3, 2); }


Download ppt "Introduction to Computer Science Recursion The Runtime Stack Unit 15."

Similar presentations


Ads by Google