Download Presentation
## Recursive methods

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

**Recursion**• A recursive method is a method that contains a call to itself • Often used as an alternative to iteration when iteration is awkward or “inelegant” • Each recursive call is given a smaller portion of the original problem • Last recursive call solves diminished problem without recursion**Example**// method writes digits of a non-negative number, stacked vertically public void write_vertical(int n) { n = Math.abs(n); if (n < 10) System.out.println(“” + n); else { write_vertical(n / 10); System.out.println(“” + n % 10); } }**Tracing recursive method write_vertical**Output: 1. write_vertical(52406); n=52406 n/10=5240 5 10. System.out.println (“” + n%10); 2 2. write_vertical(n/10) ; n=5240 n/10=524 9. System.out.println(n%10); 4 3. write_vertical(n/10); n=524 n/10=52 0 8. System.out.println (“” + n%10); 6 4. write_vertical(n/10); n=52 n/10=5 7. System.out.println (“” + n%10); 5. write_vertical(n/10); n=5 Stop recursion! 6. System.out.println(“” + n);**Elements of recursive method**• Base case: problem is simplified to the point where recursion becomes unnecessary: n < 10 • Variant expression: the part of the problem that changes, making the problem smaller: n • Recursive call: method calls itself: write_vertical (n / 10);**How recursion works**• Activation record: memory block that stores all the information a method needs to work: • values of local variables & parameters • where method should return to (so calling method can resume execution)**How recursion works**• When a method call is encountered, execution of current method ceases • Information for newly called method is stored in an activation record • Method executes**How recursion works**• If new method contains another method call, the process just described repeats • Each recursive call generates its own activation record • as each recursive call is encountered, previous activation record is stored on run-time stack • when last call fails to generate a new activation record, stacked calls are removed (in reverse of the order they were stored), and each process continues in succession**Remember, for a recursive method to be successful ...**• Must be a problem with one or more cases in which some subtasks are simpler versions of the original problem - use recursion for these • Must also have one or more cases in which entire computation is accomplished without recursion (base case)**Another example: the powers method**• Suppose you wanted to find the value of Xn • For most values of n, we can solve this iteratively using a simple loop: int answer = 1; for (int c = 1; c <= n; c++) answer *= X; • We can take care of the cases of n=1 or n=0 with simple if statements; but what about a negative value of n?**Finding a recursive solution**• We can observe that for any value of n, Xn is equal to X * X(n-1) • Armed with this information, we can easily develop a recursive solution that covers all values of X and n**Recursive power method**double rpower (double X, int n) { if (X == 0) return 0; else if (n == 0) return 1; else if (n > 0) return X * rpower(X, n-1); else // n < 0 return 1 / rpower(X, -n); }**1 if N = 1**• factorial( N ) = • N * factorial( N-1 ) otherwise Another example: Factorial • The factorial of N is the product of the first N positive integers: N * (N – 1) * (N – 2 ) * . . . * 2 * 1 • The factorial of N can be defined recursively as**public int factorial( int N ) {if( N == 1 ) {**• return 1;}else{return N * factorial( N-1 );}} Test to stop or continue. End case: recursion stops. Recursive case: recursion continues. Recursive Method • An recursive method is a method that contains a statement (or statements) that makes a call to itself. • Implementing the factorial of N recursively will result in the following method.**Another example: Anagram**• Anagram: A word or phrase formed by rearranging the letters of another word or phrase. For example, Elvis to Lives. • We can use a recursive method to derive all anagrams of a given word. • When we find the end case (an anagram), we will print it out.**C T A**A T C A C T T C A T A C Anagrams Anagram • List all anagrams of a given word. C A T Word**Recursion**A T C Rotate Left T C A Recursion Rotate Left C A T Recursion Anagram Solution • The basic idea is to make recursive calls on a sub-word after every rotation. Here’s how: C A T C T A A T C A C T T C A T A C**Anagram Algorithm**• We find the anagrams by rotating the positions of the letters. • The trick is, when the method is called recursively, we pass a word with the first letter cut off. So the words being passed to successive calls are getting shorter and shorter. • However, we must access all letters of the word in order to print it out.**Anagram Algorithm**• We solve this problem by passing two parameters: the prefix and the suffix of a word. • In each successive call, the prefix increases by one letter and the suffix decreases by one letter. • When the suffix becomes one letter only, the recursion stops.**Test**End case Recursive case Anagram Method publicvoidanagram( String prefix, String suffix ) { String newPrefix, newSuffix; intnumOfChars = suffix.length(); if(numOfChars == 1) { //End case: print out one anagram System.out.println( prefix + suffix ); } else{ for(inti = 1; i <= numOfChars; i++ ) { newSuffix = suffix.substring(1, numOfChars); newPrefix = prefix + suffix.charAt(0); anagram( newPrefix, newSuffix ); //recursive call //rotate left to create a rearranged suffix suffix = newSuffix + suffix.charAt(0); } } }**A classic: the Towers of Hanoi**• Initial situation: a stack of donut-shaped disks stacked in in order of decreasing size from bottom to top on a wooden peg • Object: move all the disks to a second peg, one at a time • third peg available as temporary holding area • at no time may a larger disk be placed on top of a smaller disk**Solving towers of Hanoi**• Simplest case: tower of one disk -- move disk to destination peg • With stack of two disks: • Move top disk to third peg • Move next disk to destination • Move disk from third peg to destination**Solving towers of Hanoi**• Simplest case: tower of one disk -- move disk to destination peg • With stack of two disks: • Move top disk to third peg • Move next disk to destination • Move disk from third peg to destination**Solving towers of Hanoi**• Simplest case: tower of one disk -- move disk to destination peg • With stack of two disks: • Move top disk to third peg • Move next disk to destination • Move disk from third peg to destination**Solving towers of Hanoi**• Simplest case: tower of one disk -- move disk to destination peg • With stack of two disks: • Move top disk to third peg • Move next disk to destination • Move disk from third peg to destination**Solving towers of Hanoi**• Simplest case: tower of one disk -- move disk to destination peg • With stack of two disks: • Move top disk to third peg • Move next disk to destination • Move disk from third peg to destination**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• Stack of 3: • Move 2 disks from 1st peg to 3rd peg, using method already described • Move 1 disk from 1st to 2nd • Move 2 disks from 3rd to 2nd**Solving towers of Hanoi**• When there are two or more disks to move, always use third peg • With more than two disks, we can solve the problem recursively by recognizing that the pegs are interchangeable -- that is, any peg can be used as source, destination, or “spare”**Solving towers of Hanoi**• In general, for a stack of n disks: • Move n-1 disks from peg 1 to peg 3 • Move 1 disk from peg 1 to peg 2 • Move n-1 disks from peg 3 to peg 2**15.4 Towers of Hanoi**• The goal of the Towers of Hanoi puzzle is to move N disks from peg 1 to peg 3: • You must move one disk at a time. • You must never place a larger disk on top of a smaller disk.**15.4 Towers of Hanoi**• This puzzle can be solved effectively using recursion. • The top N-1 disks must be moved to peg 2, allowing you to then move the largest disk from peg 1 to peg 3. • You can then move the N-1 disks from peg 2 to peg 3.**15.4 Towers of Hanoi**public void towersOfHanoi (int N, int from, int to, int spare) { if (N == 1) { moveOne(from, to); } else { towersOfHanoi(N-1, from, spare, to); moveOne (from, to); towersOfHanoi(N-1, spare, to, from); } } private void moveOne(int from, int to) { System.out.println(from + “--->” + to); }**public intfibonacci( intN ) {**if(N == 0 || N == 1) { return1; } else{ returnfibonacci(N-1) + fibonacci(N-2); } } When Not to Use Recursion • When recursive algorithms are designed carelessly, it can lead to very inefficient and unacceptable solutions. • For example, consider the following:**Excessive Repetition**• Recursive Fibonacci ends up repeating the same computation numerous times.**publicintfibonacci( intN ) {**intfibN, fibN1, fibN2, cnt; if(N == 0 || N == 1 ) { return1; } else{ fibN1 = fibN2 = 1; cnt = 2; while( cnt <= N ) { fibN = fibN1 + fibN2; //get the next fib no. fibN1 = fibN2; fibN2 = fibN; cnt ++; } returnfibN; } } Nonrecursive Fibonacci**When Not to Use Recursion**• In general, use recursion if • A recursive solution is natural and easy to understand. • A recursive solution does not result in excessive duplicate computation. • The equivalent iterative solution is too complex.**Preventing infinite recursion**• One-level recursion: every case is either a stopping case or makes a recursive call to a stopping case • Since most recursive functions are, or have the potential to be, recursive beyond just one level, need more general method for determining whether or not recursion will stop**Preventing infinite recursion**• Define a variant expression • numeric quantity that decreases by a fixed amount on each recursive call • in towers of Hanoi, variant expression was height -- each recursive call used height -1 as parameter • Base case is when variant expression is less than or equal to its threshold value**Proving correctness of a recursive function**• Show that there is no infinite recursion: • define the variant expression • ensure that it reaches its threshold value • In other words, show that the function always terminates eventually