Presentation is loading. Please wait.

Presentation is loading. Please wait.

Recursion Recursion Chapter 12. Outline n What is recursion n Recursive algorithms with simple variables n Recursion and the run-time stack n Recursion.

Similar presentations


Presentation on theme: "Recursion Recursion Chapter 12. Outline n What is recursion n Recursive algorithms with simple variables n Recursion and the run-time stack n Recursion."— Presentation transcript:

1 Recursion Recursion Chapter 12

2 Outline n What is recursion n Recursive algorithms with simple variables n Recursion and the run-time stack n Recursion and arrays n Recursion and linked structures n Recursion and complexity  proof by induction

3 What is Recursion n Recursion is a kind of “Divide & Conquer” n Divide & Conquer  Divide problem into smaller problems  Solve the smaller problems n Recursion  Divide problem into smaller versions of itself  Smallest version(s) can be solved directly

4 Recursive Structures n Getting the smallest doll from a set of Russian dolls: n If this isn’t the smallest doll  open it up  get the smallest doll from the set of Russian dolls inside

5 “Recursive” Images n Image where smaller part is same as whole  but smaller (duh!) n Fern has fronds  “fronds” are just smaller ferns

6 Recursive Algorithms n Recursive algorithm calls itself  open Russian dolls: open doll and open the (smaller) Russian dolls inside  draw a fern: draw the stem, then draw three (smaller) ferns at the end of the stem n Problem: when to stop?  Russian dolls: this doll won’t open  ferns: this fern is less than one pixel tall

7 Coding Recursively n Remember the two imperatives:  SMALLER! »when you call the method inside itself, one of the arguments has to be smaller than it was  STOP! »if the argument that gets smaller is very small (usually 0 or 1), then don’t do the recursion

8 Recursive Countdown n Print the numbers from N down to 1  recursive method (stop when N is zero) public static void countDownFrom(int n) { if (n > 0) {// STOP if n == 0! if (n > 0) {// STOP if n == 0! System.out.print(n + " "); System.out.print(n + " "); countDownFrom(n - 1);// SMALLER! countDownFrom(n - 1);// SMALLER! }} 10 9 8 7 6 5 4 3 2 1 print 10; count down from 9 …. to count down from 10:

9 Recursive Countdown n Print the numbers from N down to 1  recursive method (stop when N is zero) public static void countDownFrom(int n) { if (n > 0) {// STOP if n == 0! if (n > 0) {// STOP if n == 0! System.out.print(n + " "); System.out.print(n + " "); countDownFrom(n - 1);// SMALLER! countDownFrom(n - 1);// SMALLER! }} 10 9 8 7 6 5 4 3 2 1 print 9; count down from 8…. to count down from 9:

10 Recursive Countdown n Print the numbers from N down to 1  recursive method (stop when N is zero) public static void countDownFrom(int n) { if (n > 0) {// STOP if n == 0! if (n > 0) {// STOP if n == 0! System.out.print(n + " "); System.out.print(n + " "); countDownFrom(n - 1);// SMALLER! countDownFrom(n - 1);// SMALLER! }} 10 9 8 7 6 5 4 3 2 1 (do nothing) to count down from 0:

11 Recursive Fern Drawing public void drawFern(double x, double y, double angle, double size) { if (size > 1.0) {// STOP if size 1.0) {// STOP if size <= 1.0! double[] end; double length = size * 0.5; end = drawStem(x, y, angle, length);// private method double smaller = size * 0.5;// SMALLER! drawFern(end[0], end[1], angle+60, smaller); drawFern(end[0], end[1], angle, smaller); drawFern(end[0], end[1], angle-60, smaller); }} This will draw a fern It’s what the drawFern method does

12 Recursive Functions n Function defined in terms of itself  one or more STOPs (“base case(s)”)  one or more SMALLERs (“recursive case(s)”) n! = 1if n == 0 n*(n-1)!otherwise Fib(n) = 1if n == 0 1if n == 1 Fib(n–1)+Fib(n–2)otherwise

13 The Factorial Method n Product of numbers from N down to 1  recursive method public static int factorial(int n) { if (n > 0) { if (n > 0) { return n * factorial(n - 1);// smaller return n * factorial(n - 1);// smaller } else { } else { return 1; // stop return 1; // stop }}

14 Getting Smaller n 4! = 4 * 3!Recursive Case4 * 6 = 24 n 3! = 3 * 2!Recursive Case3 * 2 = 6 n 2! = 2 * 1!Recursive Case2 * 1 = 2 n 1! = 1 * 0!Recursive Case1 * 1 = 1 n 0! = 1Base Case n! = 1if n == 0 n*(n-1)!otherwise Base Case Recursive Case

15 Calling a Recursive Function n Just like calling any other function System.out.println(factorial(5)); n The function returns the factorial of what you give it  because that’s what it does  it returns the factorial every time you call it  including when you call it inside its definition

16 Tracing the Recursion n Each call to the function is independent  it has its own argument(s)  it has its own local variables n But we very well might get confused  20 or 30 variables all named “n” lying around n The computer does not  it uses the “run-time stack” to keep track

17 Tracing the Recursion n Don’t try to trace the calls normally  it’s very confusing n Stack up method calls  main calls factorial(4)  in factorial(4): »4 > 0, so »return 4 * factorial(3) »in factorial(3): 3 > 0, so3 > 0, so return 3 * factorial(2)return 3 * factorial(2) main System.out.println(…) factorial(4) return 4 * … factorial(3) return 3 * … factorial(2) return 2 * … factorial(1) return 1 * … main System.out.println(24) factorial(4) return 4 * 6 factorial(3) return 3 * 2 factorial(2) return 2 * 1 factorial(1) return 1 * 1 factorial(0) return 1

18 Exercise n Write a recursive function to calculate the (non-negative integer) power of an integer  Hint: it’ll look a LOT like the one for factorial n k = 1if k == 0 n*n k-1 otherwise

19 Towers of Hanoi n Buddhist monks in Hanoi n Set the task of moving golden disks (64) around diamond needles (3)  all disks different sizes  never put a bigger disk on a littler one n When all 64 disks have been moved from the starting needle to the ending, the universe will end (In class demo – 4 disks)

20 What Would be Easy? n What if there were only one disk? Start PegEnd PegExtra Peg

21 More Disks? Start Peg (5)End Peg (5)Extra Peg (5) Get top disks “out of the way” (takes MANY moves) Start Peg (4)Extra Peg(4)End Peg (4)

22 Towers of Hanoi (5 disks) Start Peg (5)End Peg (5)Extra Peg (5) Move bottom disk (one move)

23 Towers of Hanoi (5 disks) Start Peg (5)End Peg (5)Extra Peg (5) Finish moving the top disks over to the end peg (MANY moves) Extra Peg (4)End Peg(4)Start Peg (4)

24 Towers of Hanoi (5 disks) Start PegEnd PegExtra Peg All done!

25 Towers of Hanoi (Version 1) n If there’s only one disk  move it to the end peg n Else  move the top disks out of the way »extra peg becomes end peg for one less disks  move the bottom disk to the end peg  move the top disks onto the end peg »start peg becomes extra peg

26 What’s Easier than One Disk? n With no disks, there’d be nothing to do!  with one disk: »move zero disks out of the way »move bottom disk to end peg »mover zero disks onto bottom disk  same as for more than one disk n Stop when n = 0 instead of when n = 1  when n = 0, do nothing

27 Towers of Hanoi (Simplified) // ----- s == start, f == finish, x == extra ----- // public static void hanoi(int n, char s, char f, char x) { if (n > 0) {// stop if n == 0 if (n > 0) {// stop if n == 0 hanoi(n - 1, s, x, f);// smaller from start to extra hanoi(n - 1, s, x, f);// smaller from start to extra System.out.println("Move a disk from " + s + " to " + f + "."); System.out.println("Move a disk from " + s + " to " + f + "."); hanoi(n - 1, x, f, s);// smaller from extra to finish hanoi(n - 1, x, f, s);// smaller from extra to finish }}

28 Recursion with Arrays n Simple recursion  Values get smaller  Hanoi(64) calls Hanoi(63)  Hanoi(63) calls Hanoi(62) n Recursion with arrays  Array length gets smaller  Look at less of the array

29 Example Array Recursion n To Print an Array in reverse  Base Case (Stop) » If the array has length zero, do nothing  Recursive Case (Smaller) » First print the last element of the array » Then print the rest of the array in reverse 61003-28185 55 18 8 -2 3 100 6

30 Print Array in Reverse n Give “length” of array to print, too  reduce “length” by 1 until get to 0 »NOTE: we’re just pretending it’s smaller public static void printInReverse(int[] arr, int len) { if (len > 0) {// stop if len == 0 if (len > 0) {// stop if len == 0 System.out.print(arr[len - 1] + " "); System.out.print(arr[len - 1] + " "); printInReverse(arr, len - 1);// “smaller” array printInReverse(arr, len - 1);// “smaller” array }}

31 Another Example n To Find the Maximum Value in an Array  Base Case » if length is 1, the only element is the maximum  Recursive Case » Get the maximum from the rest of the array... »...& compare it to the last element » Return the bigger 61003-28185 1005

32 Exercise n Translate the (recursive) algorithm from the previous slide into Java  Base Case » if length is 1, the only element is the maximum  Recursive Case » Get the maximum from the rest of the array... »...& compare it to the last element » Return the bigger Remember to use a “pretend” length

33 Working From Both Ends n Sometimes we want to be able to shorten the array at either end n Pass start and end points instead of length n Done when  lo > hi (for len==0), or  lo == hi (for len==1) n “Sub-Array processing”

34 Working From Both Ends n Alternate way to find array maximum  compare first and last elements  drop the smaller out of range we’re using  stop when array has only one element left »maximum is that one element 61003-28185 100

35 Working From Both Ends n Alternate way to find array maximum public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) { if (lo == hi) { return arr[lo];// stop! return arr[lo];// stop! } else if (arr[lo] > arr[hi]) { } else if (arr[lo] > arr[hi]) { return maximum(arr, lo, hi - 1);// smaller return maximum(arr, lo, hi - 1);// smaller } else { } else { return maximum(arr, lo + 1, hi);// smaller return maximum(arr, lo + 1, hi);// smaller }}

36 Array Splitting n Sub-array processing can get rid of more than one element at a time n Binary split is a common method  do top “half” and bottom “half” separately  combine to get answer 61003-28185 10018 100

37 Array Splitting n Alternate way to find array maximum public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) { if (lo == hi) { return arr[lo];// stop! return arr[lo];// stop! } else { } else { int mid = lo + (hi - lo) / 2; int mid = lo + (hi - lo) / 2; int maxLo = maximum(arr, lo, mid); // smaller! int maxLo = maximum(arr, lo, mid); // smaller! int maxHi = maximum(arr, mid+1, hi); // smaller! int maxHi = maximum(arr, mid+1, hi); // smaller! return (maxLo > maxHi) ? maxLo : maxHi; return (maxLo > maxHi) ? maxLo : maxHi; }}

38 Array Recursion Exercise n Given an array and a number, find out if the number is in the array (contains method)  Base Case(s) » ?  Recursive Case(s) » ?

39 Recursion with Linked Structures n Simple recursion  Values get smaller n Recursion with arrays  Array length gets smaller n Recursion with linked structures  look at first element  if necessary, look at the rest

40 Example Linked Recursion n To Print a Linked List in reverse  Base Case (Stop) » If the list is empty, do nothing  Recursive Case (Smaller) » Print the rest of the elements in reverse order » Then print the first element 5 18 8 -2 3 1005 18 8 -2 3 100 6 6&100&3&-2&8&18&5/

41 Linked Structure Recursion n Print linked structure in reverse  give first node to the method private void printInReverse(Node first) { if (first != null) {// stop if list is empty! if (first != null) {// stop if list is empty! printInReverse(first.next); // smaller! printInReverse(first.next); // smaller! System.out.println(first.data + " "); System.out.println(first.data + " "); }}

42 Exercise n Write a recursive method to find whether a linked structure contains a given value  contains(8)  true  contains(15)  false  hint: contains(6): true or false? 6&100&3&-2&8&18&5/

43 Recursive Algorithm Analysis n Still in terms of size of problem  size of n for factorial(n), fibonacci(n), …  size of array/linked structure in printInReverse, findMaximum, … n Base case probably just one operation n Recursive case  recursive count  amount of work for n in terms of amount of work for n - 1

44 Work for printInReverse (Array) n N is the “length” of the array (len) public static void printInReverse(int[] arr, int len) { if (len > 0) {// stop if len == 0 if (len > 0) {// stop if len == 0 System.out.print(arr[len - 1] + " "); System.out.print(arr[len - 1] + " "); printInReverse(arr, len - 1);// “smaller” array printInReverse(arr, len - 1);// “smaller” array }}  if len == 0: compare len to 0: W(0) = 1  if len > 0: compare len to 0, print arr[len-1], call printInReverse with len-1: »W(len) = 2 + W(len - 1)

45 Recurrence Relation n When W(n) defined in terms of W(n – 1)…  or some other smaller value than n n … it’s called a recurrence relation n It’s a recursive definition of W  has a base case (n = 0 or n = 1 or …)  has a recursive case

46 Solving by Inspection n Work for printInReverse:  W(0) = 1(change)  W(1) = 2 + W(0) = 3+2  W(2) = 2 + W(1) = 5+2  W(3) = 2 + W(2) = 7+2  W(4) = 2 + W(3) = 9+2  …linear: factor of 2  W(N) = 2N + 1?

47 Proof by Induction n Suppose W(n) = 2n + 1 for n < N n What is W(N)?  W(N) = 2 + W(N – 1)  but N – 1 < N, so: »W(N – 1) = 2(N – 1) + 1 = 2N – 2 +1 = 2N – 1  W(N) = 2 + 2N – 1 = 2N – 1 + 2 = 2N + 1  so W(N) also = 2N + 1  and that’s for any N > 0

48 Array Splitting public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) {// 1 comparison if (lo == hi) {// 1 comparison return arr[lo];// 1 array access return arr[lo];// 1 array access } else { } else { int mid = lo + (hi - lo) / 2;// 3 math ops int mid = lo + (hi - lo) / 2;// 3 math ops int maxLo = maximum(arr, lo, mid);// 1 asgn + REC int maxLo = maximum(arr, lo, mid);// 1 asgn + REC int maxHi = maximum(arr, mid+1, hi);// 1 asgn + REC int maxHi = maximum(arr, mid+1, hi);// 1 asgn + REC return (maxLo > maxHi) ? maxLo : maxHi;// 1 comparison return (maxLo > maxHi) ? maxLo : maxHi;// 1 comparison }} W(1) = 2+W / +N W(2) = 6 + 2W(1) = 6 + 2(2) = 10+ 8 / +18N – 6 W(4) = 6 + 2W(2) = 6 + 2(10) = 26+16 / +28N – 6 W(8) = 6 + 2W(4) = 6 + 2(26) = 58+32 / +48N – 6 W(16) = 6 + 2W(8) = 6 + 2(58) = 122+64 / +88N – 6

49 findMaximum by Splitting n Split array into two (nearly equal) parts  look at only powers of 2 »even splits all the way down  looks like W(N) = 8N – 6 »linear »works for N <= 16  do induction on 2N instead of N+1  (later we’ll do 2N+1)

50 Proof by Induction (Part 1) n Assume W(n) = 8n – 6 for n < 2N n What’s W(2N)?  W(2N) = 6 + 2W(N)  but N < 2N, so W(N) = 8N – 6…  … so W(2N) = 6 + 2(8N–6) = 6 + 16N – 12 = 16N – 6 = 8(2N) – 6  same formula works for all even N

51 Proof by Induction (Part 2) n Assume W(n) = 8n – 6 for n < 2N n What’s W(2N + 1)?  W(2N + 1) = 6 + W(N) + W(N+1)  but N < N+1 < 2N, so …  W(2N + 1) = 6 + (8N – 6) + (8(N+1) – 6) = 6 + 8N – 6 + 8N + 8 – 6 = 16N + 8 – 6 = 8(2N+1) – 6  same formula works for all odd N

52 Towers of Hanoi n N = number of disks n Work = number of moves  W(0) = 0(change)  W(1) = W(0) + 1 + W(0) = 1+1  W(2) = W(1) + 1 + W(1) = 3+2  W(3) = W(2) + 1 + W(2) = 7+4  W(4) = W(3) + 1 + W(3) = 15+8  W(5) = W(4) + 1 + W(4) = 31+16

53 Solve by Inspection n Work doubles at each step of N  sounds exponential  compare work with 2 N  2 N = W(N) + 1  so work = 2 N – 1  exponential NW(N)2N2N 001 112 234 378 41516 53132 N2 N – 12N2N

54 Proof by Induction n Assume W(n) = 2 n – 1 for n < N n What’s W(N)?  W(N) = 1 + 2W(N–1) = 1 + 2(2 N–1 – 1) = 1 + 2(2 N–1 – 1) = 1 + 2 N – 2 = 2 N – 1  formula works for all N

55 Exercise n How much work is done by printInReverse for the linked structure? private void printInReverse(Node first) { if (first != null) {// stop if list is empty! if (first != null) {// stop if list is empty! printInReverse(first.next); // smaller! printInReverse(first.next); // smaller! System.out.println(first.data + " "); System.out.println(first.data + " "); }}  write recurrence relation  solve order of magnitude

56 Bad Recursion n Recursion often shorter than loops  especially when double recursion is needed »like in towers of Hanoi problem n Recursion usually same complexity as loops  but NOT ALWAYS  especially if you get double recursion

57 Fibonacci Recursion n Fibonacci uses double recursion  count number of additions required public static int fibonacci(int n) { if (n <= 1) return 1; if (n <= 1) return 1; else return fibonacci(n-1) + fibonacci(n-2); else return fibonacci(n-1) + fibonacci(n-2);} »W(0) = W(1) = 0 »W(2) = 1 + W(1) + W(0) = 1 + 0 + 0 = 1+1 »W(3) = 1 + W(2) + W(1) = 1 + 1 + 0 = 2+1 »W(4) = 1 + W(3) + W(2) = 1 + 2 + 1 = 4+2 »W(5) = 1 + W(4) + W(3) = 1 + 4 + 2 = 7+3 »W(6) = 1 + W(5) + W(4) = 1 + 7 + 4 = 12+5

58 Too Complicated n Assume that the work is increasing  standard assumption n Thus W(N-1) > W(N-2) n Thus 1 + W(N-1) + W(N-2) > 1 + 2W(N-2) n So let’s solve that recurrence relation  work for fibonacci will be worse than that

59 Simplified Equations n Using W(N) = 1 + 2W(N-2) »W(0) = 0W(1) = 0 »W(2) = 1 + 2W(0) = 1 + 2(0) = 1W(3) = 1 + 2W(1) = 1 »W(4) = 1 + 2W(2) = 1 + 2(1) = 3W(5) = 1 + 2W(3) = 3 »W(6) = 1 + 2W(4) = 1 + 2(3) = 7W(7) = 1 + 2W(5) = 7 »W(8) = 1 + 2W(6) = 1 + 2(7) = 15W(9) = 1 + 2W(7) = 15 »W(10) = 1 + 2W(8) = 1 + 2(15) = 31…  similar to towers of Hanoi: W(N) = 2 N – 1  but here a bit smaller: W(N) = 2 N/2 – 1  but still exponential »and work for fibonacci is worse

60 Can We Do Better? n For Fibonacci? Yes! We can do O(N) int f1 = 1, f2 = 1; while (n > 1) { int f3 = f1 + f2; f1 = f2; f2 = f3; --n; } return f2; n For towers of Hanoi? No!  the number of moves required is exponential  there’s no way to do better than that

61 Questions


Download ppt "Recursion Recursion Chapter 12. Outline n What is recursion n Recursive algorithms with simple variables n Recursion and the run-time stack n Recursion."

Similar presentations


Ads by Google