recursion
play

Recursion q Specify it in a comment before method's header n - PDF document

2/14/16 Preliminaries: programming as a contract n Specifying what each method does Recursion q Specify it in a comment before method's header n Precondition q What is assumed to be true before the method is executed q Caller obligation Chapter


  1. 2/14/16 Preliminaries: programming as a contract n Specifying what each method does Recursion q Specify it in a comment before method's header n Precondition q What is assumed to be true before the method is executed q Caller obligation Chapter 5.4 in Rosen n Postcondition Chapter 11 in Savitch q Specifies what will happen if the preconditions are met – what the method guarantees to the caller q Method obligation Example Enforcing preconditions /* /* ** precondition: n >= 0 ** precondition: n >= 0 ** postcondition: return value satisfies: ** postcondition: return value satisfies: ** result == n! ** result == n! */ */ int factorial (int n) { int factorial (int n) { if (n < 0) } throw new ArithmeticException(“cannot compute factorial of a neg number!”); } 1

  2. 2/14/16 What about postconditions? Enforcing preconditions /* /* ** precondition: n >= 0 ** precondition: x >= 0 ** postcondition: return value satisfies: ** postcondition: return value satisfies: ** result == n! ** result * result == x */ */ int factorial (int n) { double sqrt (double x) { assert result == n!; if (x < 0) } throw new ArithmeticException(“you Java provides a mechanism called assertions to verify that tried to take sqrt of a neg number!”); postconditions hold } What does this method do? Recursion /** n recursion : The definition of an operation in terms * precondition n>0 of itself. * postcondition ?? */ q Solving a problem using recursion depends on solving private void printStars(int n) { if (n == 1) { smaller occurrences of the same problem. System.out.println("*"); } else { System.out.print("*"); n recursive programming : Writing methods that printStars (n - 1); call themselves } } q directly or indirectly q An equally powerful substitute for iteration (loops) q But sometimes much more suitable for the problem 2

  3. 2/14/16 Definition of recursion Recursive Acronyms recursion: n. Dilbert: Wally, would you like to be on my TTP project? Wally: What does "TTP" stand for? See recursion. Dilbert: It's short for T he T TP P roject. I named it myself. — Dilbert, May 18, 1994 GNU — GNU's Not Unix KDE — KDE Desktop Environment PHP - PHP: Hypertext Preprocessor PNG — PNG's Not GIF (officially "Portable Network Graphics") RPM — RPM Package Manager (originally "Red Hat Package Manager") http://search.dilbert.com/comic/Ttp Why learn recursion? Exercise n A different way of thinking about problems n (To a student in the front row) How many students are directly behind you? n Can solve some problems better than q We all have poor vision, and can iteration only see the people right next to us. n Leads to elegant, simple, concise code So you can't just look back and count. (when used well) q But you are allowed to ask n Some programming languages ("functional" questions of the person behind you. languages such as Scheme, ML, and q How can we solve this problem? ( recursively ) Haskell) use recursion exclusively (no loops) 3

  4. 2/14/16 The idea Recursive algorithm n Recursion is all about breaking a big problem n Number of people behind me: into smaller occurrences of that same problem. q If there is someone behind me, ask him/her how many people are behind him/her. q Each person can solve a small part of the problem. When they respond with a value N , then I will answer N + 1 . n What is a small version of the problem that would be easy to n answer? q If there is nobody behind me, I will answer 0 . What information from n a neighbor might help you? Recursive structures Expressions represented by trees + n A directory has n A tree is q files q a node * * and with a b c d q (sub) directories q zero or more sub trees n An expression has a*b + c*d * examples: q operators + + a*b + c*d q operands, which are a b c d n variables (a+b)*(c+d) n constants n (sub) expressions 4

  5. 2/14/16 Structure of recursion Cases n Each of these examples has n Every recursive algorithm has at least 2 cases: q base case : A simple instance that can be answered q recursive parts (directory, expression, tree) directly. q non recursive parts (file, variables, nodes) q recursive case : A more complex instance of the problem that cannot be directly answered, but can n Always need non recursive parts. Why? instead be described in terms of smaller instances. q Can have more than one base or recursive case, but all have at least one of each. n Same goes for recursive algorithms. q A crucial part of recursive programming is identifying these cases. Base and Recursive Cases: Example Recursion Zen n An even simpler, base case is n=0 : public void printStars(int n) { if (n == 1) { public void printStars(int n) { // base case; print one star if (n == 0) { System.out.println("*"); // base case; end the line of output } else { System.out.println(); // recursive case; print one more star } else { System.out.print("*"); // recursive case; print one more star printStars(n - 1); System.out.print("*"); } printStars(n - 1); } } } q Recursion Zen : The art of identifying the best set of cases for a recursive algorithm and expressing them elegantly. 5

  6. 2/14/16 Everything recursive can be done non- Computing the maximum of an array recursively We would like to compute the maximum of the // Prints a line containing a given number of stars. elements in an array. // Precondition: n >= 0 public void printStars(int n) { for (int i = 0; i < n; i++) { System.out.print("*"); Need to identify base case and recursive case, } System.out.println(); and what to do in each. } Computing the maximum of an array Exercise n Let’s write a method reverseLines(Scanner scan) The idea: that reads lines using the scanner and prints them in reverse order. Base case: array of size 1: return the element q Use recursion without using loops. Recursive case: compute maximum of two q Example input: Expected output: numbers – the first element, and the maximum this no? of the rest of the array is fun fun is no? this q What are the cases to consider? How can we solve a small part of the problem at a time? n What is a file that is very easy to reverse? n 6

  7. 2/14/16 Reversal pseudocode Reversal solution n Reversing the lines of a file: public void reverseLines(Scanner input) { if (input.hasNextLine()) { q Read a line L from the file. // recursive case q Print the rest of the lines in reverse order. String line = input.nextLine(); reverseLines(input); q Print the line L. System.out.println(line); } } n If only we had a way to reverse the rest of the lines of the file.... q Where is the base case? Tracing our algorithm Recursive power example n Call stack : The method invocations active at n Write a method that computes x n . any given time. x n = x * x * x * ... * x (n times) public void reverseLines(Scanner input) { if (input.hasNextLine()) { reverseLines(scanner); n An iterative solution: String line = input.nextLine(); // ”this" public void reverseLines(Scanner input) { reverseLines(input); if (input.hasNextLine()) { public int pow(int x, int n) { System.out.println(line); String line = input.nextLine(); // ”is" public void reverseLines(Scanner input) { } reverseLines(input); int product = 1; if (input.hasNextLine()) { } System.out.println(line); String line = input.nextLine(); // ”fun" for (int i = 0; i < n; i++) { public void reverseLines(Scanner input) { } reverseLines(input); if (input.hasNextLine()) { product = product * x; } System.out.println(line); String line = input.nextLine(); // ”no?" public void reverseLines(Scanner input) { } } reverseLines(input); if (input.hasNextLine()) { // false } return product; System.out.println(line); ... } } } } } output: input file: no? this fun is is fun this no? 28 7

  8. 2/14/16 Exercise solution How recursion works // Returns base ^ exponent. n Each call sets up a new instance of all the // Precondition: exponent >= 0 parameters and the local variables public int pow(int x, int n) { if (n == 0) { n When the method completes, control returns to // base case; any number to 0th power is 1 the method that invoked it (which might be return 1; } else { another invocation of the same method) // recursive case: x^n = x * x^(n-1) return x * pow(x, n-1); pow(4, 3) = 4 * pow(4, 2) } = 4 * 4 * pow(4, 1) } = 4 * 4 * 4 * pow(4, 0) = 4 * 4 * 4 * 1 = 64 30 Infinite recursion An optimization n A method with a missing or badly written base n Notice the following mathematical property: case can causes infinite recursion 3 12 = (3 2 ) 6 = (9) 6 = (81) 3 = 81*(81) 2 public int pow(int x, int y) { q We can use it to improve our pow method! return x * pow(x, y - 1); // Oops! No base case } q What is the “trick”? pow(4, 3 ) = 4 * pow(4, 2) q How can we incorporate this optimization into our = 4 * 4 * pow(4, 1) pow method? = 4 * 4 * 4 * pow(4, 0) = 4 * 4 * 4 * 4 * pow(4, -1) q What is the benefit? = 4 * 4 * 4 * 4 * 4 * pow(4, -2) = ... crashes: Stack Overflow Error! 31 8

Recommend


More recommend