Presentation is loading. Please wait.

Presentation is loading. Please wait.

Week 5 - Monday.  What did we talk about last time?  Linked list implementations  Stacks  Queues.

Similar presentations


Presentation on theme: "Week 5 - Monday.  What did we talk about last time?  Linked list implementations  Stacks  Queues."— Presentation transcript:

1 Week 5 - Monday

2  What did we talk about last time?  Linked list implementations  Stacks  Queues

3

4 Infix to Postfix Converter

5

6  For some reason, people like to have crazy loops:  For this (relatively simple) case, it's not terrible, but the more complex it gets, the harder it is to think about indexes that jump around  Even so, what do i and j mean in this case? for( int i = 0; i < height; ++i ) for( int j = 0; j < width*3; j += 3 ) { data[i][j] = 255 – data[i][j]); data[i][j + 1] = 255 – data[i][j + 1]; data[i][j + 2] = 255 – data[i][j + 2]; }

7  I like to keep my for loop indexes simple, because loops are hard to thinking about  Written this way, my indexes are rows and columns: for( int row = 0; row < height; ++row ) for( int column = 0; column < width; ++column ) { data[row][3*column] = 255 – data[row][3*column]); data[row][3*column + 1] = 255 – [row][3*column + 1]; data[row][3*column + 2] = 255 – [row][3*column + 2]; }

8  Or even better:  I don't object to i and j, but a loop index should mean something for( int row = 0; row < height; ++row ) for( int column = 0; column < width; ++column ) for( int color = 0; color < 3; ++color ) data[row][3*column + color] = 255 – data[row][3*column + color]);

9

10  Defining something in terms of itself  To be useful, the definition must be based on progressively simpler definitions of the thing being defined

11  It is possible to define something recursively from the bottom up  We start with a simple pattern and repeat the pattern, using a copy of the pattern for each part of the starting pattern

12 Explicitly:  n! = (n)(n – 1)(n – 2) … (2)(1) Recursively:  n! = (n)(n – 1)!  6! = 6 ∙ 5!  5! = 5 ∙ 4! ▪ 4! = 4 ∙ 3! ▪ 3! = 3 ∙ 2!  2! = 2 ∙ 1!  1! = 1  6! = 6 ∙ 5 ∙ 4 ∙ 3 ∙ 2 ∙ 1 = 720

13  PHP  PHP: Hypertext Processor ▪ (PHP: Hypertext Processor): Hypertext Processor ▪…▪…  XINU  XINU Is Not Unix ▪ (XINU Is Not Unix) Is Not Unix ▪…▪…

14 Two parts:  Base case(s)  Tells recursion when to stop  For factorial, n = 1 or n = 0 are examples of base cases  Recursive case(s)  Allows recursion to progress  "Leap of faith"  For factorial, n > 1 is the recursive case

15

16  Top down approach  Don’t try to solve the whole problem  Deal with the next step in the problem  Then make the "leap of faith"  Assume that you can solve any smaller part of the problem

17 Problem  Problem: You want to walk to the door  Base case (if you reach the door):  You’re done!  Recursive case (if you aren’t there yet):  Take a step toward the door Problem

18  Base case (n  1):  1! = 0! = 1  Recursive case (n > 1):  n! = n(n – 1)!

19 public static long factorial( int n ) { if( n <= 1 ) return 1; else return n*factorial( n – 1 ); } Base Case Recursive Case

20  Given an integer, count the number of zeroes in its representation  Example:  13007804  3 zeroes

21  Base cases (number less than 10):  1 zero if it is 0  No zeroes otherwise  Recursive cases (number greater than or equal to 10):  One more zero than the rest of the number if the last digit is 0  The same number of zeroes as the rest of the number if the last digit is not 0

22 public static int zeroes( int n ) { if( n == 0 ) return 1; else if( n < 10 ) return 0; else if( n % 10 == 0 ) return 1 + zeroes( n / 10 ); else return zeroes( n / 10 ); } Base Cases Recursive Cases

23  Given an array of integers in (ascending) sorted order, find the index of the one you are looking for  Useful problem with practical applications  Recursion makes an efficient solution obvious  Play the High-Low game

24  Base cases:  The number in the middle of the range is the one you are looking for. Return its index.  The number isn’t in the range you are looking at. Return -1.  Recursion cases:  The number in middle of the range is too high. Look in the range below it.  The number in the middle of the range is too low. Look in the range above it.

25 public static int search( int[] array, int n, int start, int end ) { int midpoint = (start + end)/2; if( array[midpoint] == n ) return midpoint; else if( start >= end ) return -1; else if( array[midpoint] < n ) return search( array, n, midpoint + 1, end ); else return search( array, n, start, midpoint ); } Base Cases Recursive Cases

26  Each recursive call splits the range in half  In the worst case, we will have to keep splitting the range in half until we have a single number left  We want to find the number of times that we have to multiply n by ½ before we get 1  n(½) x = 1  n = 2 x  x = log 2 (n)

27 Pay no attention to the man behind the curtain…

28  How does it actually work inside a computer?  Is there a problem with calling a function inside the same function?  How does the computer keep track of which function is which?

29  As you know, a stack is a FILO data structure used to store and retrieve items in a particular order  Just like a stack of blocks: Push Pop

30  In the same way, the local variables for each function are stored on the stack  When a function is called, a copy of that function is pushed onto the stack  When a function returns, that copy of the function pops off the stack main solve Call main solve factorial Call main solve Return

31  Each copy of factorial has a value of n stored as a local variable  For 6! : 6*factorial(5) 5*factorial(4) 4*factorial(3) 3*factorial(2) 2*factorial(1) 1 x = factorial(6); factorial(6) factorial(5)factorial(4)factorial(3)factorial(2) factorial(1)720 1202462 1

32

33  Recursion is a great technique  One of its strengths is in writing concise code to solve a problem  Some recursive solutions are very efficient  Some are not  It pays to be aware of both

34  Find the sum of the integers 1 through n  Example: n = 8  sum(8) = 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1  sum(8) = 36

35  Base case (n = 1):   Recursive case (n > 1): 

36 public static int sum( int n ) { if( n == 1 ) return 1; else return n + sum( n – 1 ); } Base Case Recursive Case

37  Recursive summing takes linear time (summing n takes n function calls)  Is there another way to find this sum?  Closed form equation   Constant time!  Remember the story of young Gauss

38  The sequence: 1 1 2 3 5 8 13 21 34 55…  Studied by Leonardo of Pisa to model the growth of rabbit populations

39  Find the n th term of the Fibonacci sequence  Simple approach of summing two previous terms together  Example: n = 7  1 1 2 3 5 8 13 1 2 3 4 5 6 7

40  Base cases (n = 1 and n = 2):  Result = 1  Recursive case (n > 2):  Result = fibonacci(n – 1) + fibonacci(n – 2)

41 public static int fib( int n ) { if( n <= 2 ) return 1; else return fib(n – 1) + fib(n – 2); } Base Case Recursive Case

42  Example: fib(6) fib(6) fib(4)fib(5)fib(4)fib(3) fib(2) fib(1) fib(2) fib(1)fib(3)fib(2) fib(1) Uh oh.

43  For most cases, calling fib() makes calls two more calls to fib(), which each make two more calls to fib(), and so on…  Many values are redundantly computed  The final running time is O(2 n/2 )

44  The recursion is fine from a mathematical perspective  We just need to avoid recomputing lower terms in the sequence  We can use the idea of carrying along both the (n – 1) term and the (n – 2) term in each recursive step

45 public static int fib2( int a, int b, int n ) { if( n <= 2 ) return b; else return fib2(b, a + b, n - 1); } //proxy method int fib( int n ) { return fib2(1, 1, n); } Base Case Recursive Case

46  We want to raise a number x to a power n, like so: x n  We allow x to be real, but n must be an integer greater than or equal to 0  Example: (4.5) 13 = 310286355.9971923828125

47  Base case (n = 0):  Result = 1  Recursive case (n > 0):  Result = x ∙ x (n – 1)

48 public static double power( double x, int n ) { if( n == 0 ) return 1; else return x * power( x, n – 1); } Base Case Recursive Case

49  Each call reduces n by 1  n total calls  What's the running time?  O(n)

50  We need to structure the recursion differently  Instead of reducing n by 1 each time, can we reduce it by a lot more?  It’s true that x n = x ∙ x (n – 1)  But, it is also true that x n = x (n/2) ∙ x (n/2)

51  Assume that n is a power of 2  Base case (n = 1):  Result = x  Recursive case (n > 1):  Result = (x (n/2) ) 2

52 public static double power2( double x, int n ) { double temp; if( n == 1 ) return x; else { temp = power2( x, n/2 ); return temp * temp; } } Base Case Recursive Case

53  Each call reduces n by half  log 2 (n) total calls  Just like binary search  Can we expand the algorithm to even and odd values of n?

54  Base case (n = 1):  Result = x  Recursive cases (n > 1):  If n is even, result = (x (n/2) ) 2  If n is odd, result = x ∙ (x ((n – 1)/2) ) 2

55 public static double power3( double x, int n ) { double temp; if( n == 1 ) return x; else if( n % 2 == 0 ) { temp = power3( x, n/2 ); return temp * temp; } else { temp = power3( x, (n – 1)/2 ); return x * temp * temp; } } Base Case Recursive Cases

56

57

58  Review for Exam 1

59  Study for Exam 1  This Friday, September 25, in class  Start working on Project 2  Sign up for new teams on Canvas immediately!  You can't partner with someone you've partnered with before  I will start docking points if you haven't picked your teams by Friday


Download ppt "Week 5 - Monday.  What did we talk about last time?  Linked list implementations  Stacks  Queues."

Similar presentations


Ads by Google