Download presentation
Presentation is loading. Please wait.
Published byMargaretMargaret Reynolds Modified over 9 years ago
1
When confronted with a new problem there are two questions you should ask: 1. Is this problem like, or a special case of, a problem that I already know how to solve? 2.Is this a problem of size n in one of its variables that I could solve if I knew the solution to an instance of the same problem (or instances of all such problems) of size less than n? Recursion
2
When the answer to the second question is “yes”, you will employ recursion. There are three steps in formulating a recursive solution to a problem. n n 1.Formulate the solution (to a problem of size n) in terms of the solution to the same problem of size less than n. n 2.Determine a “base case” (at n = 0) where the solution to the problem is trivial. 3.Terminate recursion when this “base case” value is reached. Recursion “rewards” procrastination by formulating the solution of a problem as a sequence of solutions to similar problems, and postponing the actual solution of any of these problems until they are trivial.
3
Recursion – Contents of Presentation 1.Recursion as a problem solving technique 2.Towers of Hanoi – An example of a recursive approach to problem solving. 3.Recursive Algorithms – The Good, the Bad, and the Ugly! a) The “Good” – Raising a base to a power. b) The “Bad” – Calculating N Factorial. c) The “Ugly” – The Fibonacci Sequence 4.Binary Search 5.Recursively Defined Grammars – Finding Palindromes
4
Example: Towers of Hanoi puzzle In this puzzle, the player begins with n disks of decreasing diameter placed one on top of the other on one of three pegs of the game board. The player must move the disks from peg to peg, using each of the three pegs, until the entire tower is moved from the starting peg to one of the others. The only rule governing the movement of the disks is that in each move a disk of larger diameter must never be placed on top of one of smaller diameter
5
Towers of Hanoi Puzzle
12
A solution to the problem of moving a tower of size n from the source peg to the destination peg using a spare peg is found by moving a tower of size n – 1 from the source peg to the spare peg, moving the bottom disk from the source peg to the destination peg, and finally moving a tower of size n – 1 from the spare peg to the destination peg.
13
public class TowersOfHanoi { private int num_disks; private int source, spare, dest;//pegs public TowersOfHanoi (int n_disks) {//see next slide} //pre-condition: n_disks > 0 //exception: error message sent and program terminates public void moveTower(int disks, int from_peg, int to_peg, int use_peg) {…} public void moveDisk(int num, int from_peg, int to_peg) {…} }; Class TowersOfHanoi -- header file
14
Class TowersOfHanoi -- implementation Class Constructor public TowersOfHanoi(int n_disks) { if ( n_disks < 1) { System.err.println( “error – must start with 1 or more disks in a tower”; exit(1); } num_disks = n_disks; source = 1; spare = 2; dest = 3; moveTower(num_disks, source, dest, spare); }
15
Class TowersOfHanoi -- implementation moveTower public void moveTower(int disks, int from_peg, int to_peg, int use_peg) { if (disks == 1) moveDisk(disks, from_peg, to_peg); else { moveTower(disks – 1, from_peg, use_peg, to_peg); moveDisk(disks, from_peg, to_peg); moveTower(disks –1, use_peg, to_peg, from_peg); }
16
moveDisk public void moveDisk(int num, int from_peg, int to_peg) { System.out.print( “moving disk number ” + num + “ from peg”) ; System.out.println(from_peg + “ to peg ” + to_peg ); } Class TowersOfHanoi -- implementation
17
public void moveTower(int disks, int from_peg, int to_peg, int use_peg) { if (disks == 1) moveDisk(disks, from_peg, to_peg); else moveTower(disks-1, from_peg, use_peg, to_peg); moveDisk(disks, from_peg, to_peg); moveTower(disks-1, use_peg, to_peg, from_peg); } 1 12 Disk source target 2 3 moveTower(3,1,3,2);1 1 moveTower(2,1,2,3);2 moveTower(1,1,3,2);3 3 1 1 3 2 2 1 2 2 moveTower(1,3,2,1);3 3 3 1 3 2 1 3 1 3 1 2 moveTower(2,2,3,1);2 2 moveTower(1,2,1,3);3 3 3 1 2 1 2 2 2 3 2 3 moveTower(1,1,3,2);3 3 1 1 3 Stack of act. Recs. screen Illustration of moveTower operation Calls to moveTower
18
Recursively Defined Functions Exponentiation --”The Good” The Good, the bad, and the ugly 1if n = 0 1/ power(b, |n|)if n < 0 power (b, n) = b * power (b, n-1)if n > 0 and odd power(b, n/2) * power(b,n/2) if n > 0 and even
19
public double power (double b, int n) { //start all recursive functions with a test for the base case //test to terminate recursion) if ( n == 0)return 1; if (n < 0) return 1/power(b, -n); if ((n % 2) == 1) return b * power(b, n-1); else { // n even and positive double temp = power(b, n/2); return temp * temp; } Recursive power function The recursive algorithm completes after at most 2*lg(n) calls
20
Recursively Defined Functions 1if n = 0 n! = n * (n – 1) !for all n > 0 Figure 2. The factorial function The “bad”
21
Recursively Defined Functions The Factorial Function public long factorial (int n) { //precondition:n >= 0 if (n < 0) { System.out.println( “error – factorial function requires non-negative argument\n”; exit(1); } if (n == 0) return 1; else return n * factorial (n – 1); } Requires n time (and space) consuming function calls
22
Recursively Defined Functions Tail Recursion public void reverse_write(const char [ ] A, int size) { if (size > 0) { System.out.print( A[size – 1]); reverse_write (A, size – 1); } The recursive factorial algorithm uses recursion as the last statement in the function, only to set the parameters for the next round of processing. This is better done by iteration! Consider this example. while(size > 0) size--;
23
public void iterative_reverse_write(const char A[ ], int size) { while (size > 0) { System.out.println( A[size – 1]); size--; } Recursively Defined Functions Eliminating Tail Recusion
24
Recursively Defined Functions public long iterative_factorial (int n) { //precondition:n >= 0 if (n < 0) { System.out.println( “error – factorial function requires non- negative argument”); exit(1); } long prod = n; while ( n > 1) { n--; prod *= n; } return prod; } Non-recursive factorial function n iterations, but much faster and uses less memory than n recursive calls!
25
Recursively Defined Functions The “ugly” – the fibonacci function 0if n = 0 fibon (n) = 1if n = 1 finbon(n-1) + fibon(n-2) if n > 1
26
Recursive fibonacci function public long fibon (long int n) { //precondition n >= 0; //exception:if n send an error message and terminate if ( n < 0 ) { System.out.println( “error – fibonacci numbers not defined over negative numbers”); exit (1); } if (n = 0)return 0;//base cases if (n = 1)return 1; return fibon(n-1) + fibon(n-2); }
27
The fibonacci function The run-time behavior of this recursive algorithm becomes exponential because the algorithm is “senile”. It “forgets” the value it obtained on a previous call and has to (recursively) recalculate the same value again. fibon(6) fibon(5) fibon(4) fibon(3) fibon(2) fibon(1) 1 + fibon(0) 0 1 fibon(1) + 2 1 fibon(2) + fibon(1) 1 + fibon(0) 0 1 3 + fibon(3) fibon(2) fibon(1) 1 + fibon((0) 0 1 + fibon(1) 1 2 5 + fibon(4) fibon(3) fibon(2) fibon(1) 1 + fibon(0) 0 1 + fibon(1) 1 2 + fibon(2) fibon(1) 1 + fibon(0) 0 1 3 8
28
An iterative fibonacci function public long iterative_fibon(long int n) { //precondition n >= 0; //exception:if n send an error message and terminate if ( n < 0 ) { System.out.println( “error – fibonacci numbers not defined over negative numbers”); exit (1); } if (n = 0)return 0;//base cases if (n = 1)return 1; long int term1 = 1, term2 = 0, hold; for (int i = 2; i <= n; i++) { hold = term1; term1 += term2; term2 = hold; } return term1; } Requires only 2 memory locations and n iterations!
29
Divide and Conquer Binary Search public int binarySearch(int [ ] A, int first, int last, int key) {..} //preconditions:list A is ordered in increasing order (not checked) //last > first (sub-list is not empty) //post conditions:list A is unchanged, if key occurs in the list the index //of (one of) the location where it occurs is returned, else //a dummy value of –1 is returned //exception:if first >= last send error message and terminate
30
Initial State of List A
31
State of List A during the first call to binary_search
32
State of List A during the third call to binary_search
33
public int binarySearch(int [ ] A, int first, int last, int key) { //check for exception if (first >= last) { System.out.println( “error – list to be searched is empty”); exit(1); } //check for termination of recursion if ((last – first) == 1) if (A[first] == key) return first; else return –1; int med = (first + last) / 2;//integer division if (key < A[med] ) binarySearch (A, first, med, key); else binarySearch (A, med, last, key); }
34
Recursively Defined Grammars Palindrome L = {w | w is a string of alphabetic characters that is the same read backwards or forwards} and the BNF grammar G is: ::= | | “a” “a” |…| “Z” ::= “a” | … | “z” | “A” | … | “Z” ::= “”
35
public boolean isPalindrome(String s) { if ( s == NULL) return TRUE; if (s.length == 1) return TRUE; int len = s.length; return boolean (s.charAt(0) == s.charAt([len-1])) && isPalindrome(s.substring(1,len-2)); } Test for a palindrome
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.