Presentation is loading. Please wait.

Presentation is loading. Please wait.

Recursion Based on slides by Alyssa Harding

Similar presentations


Presentation on theme: "Recursion Based on slides by Alyssa Harding"— Presentation transcript:

1 Recursion Based on slides by Alyssa Harding
CSE 143 Lecture 13 Recursion Based on slides by Alyssa Harding

2 Recursion recursion: The definition of an operation in terms of itself. Solving a problem using recursion depends on solving smaller occurrences of the same problem. recursive programming: Writing methods that call themselves to solve problems recursively. An equally powerful substitute for iteration (loops) Particularly well-suited to solving certain types of problems

3 Why learn recursion? Many programming languages ("functional" languages such as Scheme, ML, and Haskell) use recursion exclusively (no loops) "cultural experience" - A different way of thinking of problems Can solve some kinds of problems better than iteration Leads to elegant, simplistic, short code (when used well) A key component of the rest of our assignments in CSE 143

4 Decimal Numbers vs. Binary Numbers
Decimal Numbers (“Base 10”) 10 Possible Digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 Ex. With 3 digits we get: 10 * 10 * 10 different patterns (0-999) We interpret these patterns as follows: 34810 = = 3 × × ×100 Binary Numbers (“Base 2”) 2 Possible Digits: 0, 1 Ex. With 3 digits we get: 2 * 2 * 2 different patterns ( ) 1012 = 1 × ×21 + 1×20 = 1 ×4 + 0 ×2 + 1×1 = = 510 4

5 Binary Numbers A few Decimal numbers written in Binary: Decimal Binary
Sum 0 × 20 1 1 × 20 2 10 1 × × 20 3 11 1 × × 20 4 100 1 × × × 20 5 101 1 × × × 20 6 110 1 × × × 20 7 111 1 × × × 20 8 1000 1 × × × × 20

6 Example: writeBinary Write a method that takes a positive decimal number as input and writes out the equivalent number in binary. How do we convert from decimal to binary? Example: What is 8574 in binary? How about the last binary digit of 8574? It’ll be 0, just like all the other even numbers in the table

7 See Stutter from Monday
Example: writeBinary This gives us an idea of how to break our problem down. Recall that we can split a decimal number to get the leading digits in base-10 and the final digit, given number 8574: To get the leading digits in base-2 and the final digit, we can do the same, given decimal number 8574: 857 4 n/10 n%10 See Stutter from Monday “The number of 10s in 8574” 4287 n/2 n%2 “The number of 2s in 8574”

8 Example: writeBinary So, what’s the base case?
public static void writeBinary(int n) { }

9 Example: writeBinary So, what’s the base case?
public static void writeBinary(int n) { if ( n < 2 ) { System.out.print(n); } else { } } We know what to do with a single binary digit, 0 or 1 9

10 Example: writeBinary What’s the recursive case?
public static void writeBinary(int n) { if ( n < 2 ) { System.out.print(n); } else { System.out.print(n%2); } } If we have a bigger number, we can still print out its last binary digit

11 Example: writeBinary What’s the recursive case?
public static void writeBinary(int n) { if ( n < 2 ) { System.out.print(n); } else { writeBinary(n/2); System.out.print(n%2); } } And we can recurse to print out the remaining part of the number

12 Another Example: sum public static int sum(int[] list) { int sum = 0;
Write a method sum that takes an array of integers as a parameter and returns the sum of the numbers in the array. public static int sum(int[] list) { int sum = 0; for (int i = 0; i < list.length; i++) { sum += list[i]; } return sum; Iterative version

13 Example: sum Write a method sum that takes an array of integers as a parameter and returns the sum of the numbers in the array using recursion. public static int sum(int[] list) { } Base Case?

14 Example: sum Write a method sum that takes an array of integers as a parameter and returns the sum of the numbers in the array using recursion. public static int sum(int[] list) { if (list.length == 0) return 0; else { ... } Base Case Break problem into smaller pieces Make progress towards base case with each recursive call

15 Example: sum public static int sum(int[] list) { if (list.length == 0)
return 0; else { ... } Break problem into smaller pieces, make progress: sum(entire list) = list[0] + sum(list starting at 1)

16 Example: sum When do we stop?
Break problem into smaller pieces, make progress: sum(entire list) = list[0] + sum(list starting at 1) sum(list starting at 1) = list[1] + sum(list starting at 2) sum(list starting at 2) = list[2] + sum(list starting at 3) sum(list starting at 3) = list[3] + sum(list starting at 4) sum(list starting at 4) = list[4] + sum(list starting at 5) ..... When do we stop?

17 Example: sum Break problem into smaller pieces, make progress:
sum(entire list) = list[0] + sum(list starting at 1) sum(list starting at 1) = list[1] + sum(list starting at 2) sum(list starting at 2) = list[2] + sum(list starting at 3) sum(list starting at 3) = list[3] + sum(list starting at 4) sum(list starting at 4) = list[4] + sum(list starting at 5) ..... sum(list starting at list.length-1) = list[list.length-1] sum(list starting at list.length) sum(list starting at list.length) = 0

18 Example: sum Current version: public static int sum(int[] list) {
if (list.length == 0) return 0; else { ... }

19 Example: sum Orig version: public static int sum(int[] list) {
if (list.length == 0) return 0; else { ... } New version: public static int sum(int[] list, int index) {

20 Example: sum public static int sum(int[] list, int index) {
if (index == list.length) return 0; else return list[index] + sum(list, index + 1); }

21 Example: sum // returns the sum of the numbers in the given array
public int sum(int[] list) { return sum(list, 0); } // computes the sum of the list starting at the given index private static int sum(int[] list, int index) { if (index == list.length) return 0; else return list[index] + sum(list, index + 1);

22 Aside: for each loop There’s another way to look at any structure that is Iterable for (int i = 0; i < <structure>.size(); i++) { <statements> } for (<type> <name> : <structure>) { <statements> } Warning: in a for each loop, you cannot remove values see which index you’re at If you need to do that, stick with a for loop! for loop for each loop 22

23 for loop vs. for each loop
ArrayList<Integer> list1 = new ArrayList<Integer>(); list1.add(42); list1.add(7); list1.add(-10); for (int i = 0; i < list1.size(); i++) { System.out.println(list1.get(i)); } for (int n : list1) { System.out.println(n); } for loop for each loop 23

24 Recursion Example: crawler
Now we want to make a crawler method that will print out files and directories Java provides us with a File object Given the file or directory we want, we can print its name public static void print(File f) { System.out.println(f.getName()); } We also want to print the contents of a directory, though

25 Example: crawler We can get an array of the files in the directory and print their names: public static void print(File f) { System.out.println(f.getName()); for (File subF : f.listFiles()) { System.out.println(“ “+subF.getName()); } }

26 Example: crawler We can get an array of the files in the directory and print their names: public static void print(File f) { System.out.println(f.getName()); for (File subF : f.listFiles()) { System.out.println(“ “+subF.getName()); } } But this only works if f is a directory, otherwise it throws a NullPointerException 26

27 Example: crawler So we check to make sure f is a directory first:
public static void print(File f) { System.out.println(f.getName()); if ( f.isDirectory() ) { for (File subF : f.listFiles()) { System.out.println(" “+subF.getName()); } } }

28 Example: crawler So we check to make sure f is a directory first:
public static void print(File f) { System.out.println(f.getName()); if ( f.isDirectory() ) { for (File subF : f.listFiles()) { System.out.println(" “+subF.getName()); } } } But this still only works for one level of directories 28

29 Example: crawler So we check to make sure f is a directory first:
public static void print(File f) { System.out.println(f.getName()); if ( f.isDirectory() ) { for (File subF : f.listFiles()) { System.out.println(" “+subF.getName()); if ( subF.isDirectory() ) { for (File subSubF : subF.listFiles() ) { } } } } } 29

30 Example: crawler So we check to make sure f is a directory first:
public static void print(File f) { System.out.println(f.getName()); if ( f.isDirectory() ) { for (File subF : f.listFiles()) { System.out.println(" “+subF.getName()); if ( subF.isDirectory() ) { for (File subSubF : subF.listFiles() ) { } } } } } Redundant! And it still only works for one more level of directories

31 Example: crawler If only we had a method that would print the files in a directory...but we do! public static void print(File f) { System.out.println(f.getName()); if ( f.isDirectory() ) { for (File subF : f.listFiles()) { print(subF); } } } We probably want to add indentation, as well

32 Example: crawler So we add a String parameter to show how much each file name should be indented public static void print(File f, String indent) { System.out.println(indent + f.getName()); if ( f.isDirectory() ) { for (File subF : f.listFiles()) { print(subF, indent + " "); } } } We don’t want our client to need to pass a String, though

33 Example: crawler Instead, we make a public method for the client and hide the extra parameter by making our other method private: public static void print(File f) { print(f, ""); } private static void print(File f, String indent) { System.out.println(indent + f.getName()); if ( f.isDirectory() ) { for (File subF : f.listFiles()) { print(subF, indent + " "); } } } Using a public/private pair is common in recursion when we want to work with extra parameters

34 Example: Sierpinski Chapter 12 in the book discusses the Sierpinski triangle, a fractal (recursive image):

35 Extra Example: pow Now we want to recursively take x to the y power
We’ll only deal with ints, so x and y must be ints This also means that y must be positive so that the return value is an int 35

36 Example: pow What’s the base case?
// returns x to the y power // pre: y >= 0 public static int pow(int x, int y) { if ( y == 0 ) { return 1; } else { } } If y is 0, we automatically know that the power is 1! 36

37 Example: pow What’s the recursive case?
// returns x to the y power // pre: y >= 0 public static int pow(int x, int y) { if ( y == 0 ) { return 1; } else { return x * pow(x,y-1); } } Otherwise, we can break it down into two smaller problems: xy = x1 × xy-1 37

38 Example: pow Taking care of negative inputs...
// returns x to the y power // if y < 0, throws IllegalArgumentException public static int pow(int x, int y) { if ( y < 0 ) { throw new IllegalArgumentException(); } else if ( y == 0 ) { return 1; } else { return x * pow(x,y-1); } } 38

39 Example: pow But is this the best way?
If I asked you to compute 232, you wouldn’t hit multiply on your calculator 32 times (hopefully!) We can also note that xy = (x2)(y/2) Example: 34 = 92 = 81 This only works for even values of y because of integer division 39

40 Example: pow Putting in our new idea...
public static int pow2(int x, int y) { if ( y < 0 ) { throw new IllegalArgumentException(); } else if ( y == 0 ) { return 1; } else if ( y % 2 == 0 ) { return pow2(x*x, y/2); } else { return x * pow2(x,y-1); } } 40


Download ppt "Recursion Based on slides by Alyssa Harding"

Similar presentations


Ads by Google