Presentation is loading. Please wait.

Presentation is loading. Please wait.

Programming with Recursion

Similar presentations


Presentation on theme: "Programming with Recursion"— Presentation transcript:

1 Programming with Recursion
COPYRIGHT © 2005, MICHAEL T. GOODRICH AND ROBERTO TAMASSIA.

2 The Recursion Pattern Recursion: when a method calls itself
Classic example--the factorial function: n! = 1· 2· 3· ··· · (n-1)· n Recursive definition: As a Java method:

3 Content of a Recursive Method
Base case(s) Values of the input variables for which we perform no recursive calls are called base cases (there should be at least one base case). Every possible chain of recursive calls must eventually reach a base case. Recursive calls Calls to the current method. Each recursive call should be defined so that it makes progress towards a base case.

4 Visualizing Recursion
Example recursion trace: Recursion trace A box for each recursive call An arrow from each caller to callee An arrow from each callee to caller showing return value recursiveFactorial ( 4 ) 3 2 1 return call * = 6 24 final answer

5 Binary Search Binary search uses a recursive method to search an array to find a specified value The array must be a sorted array: a[0]≤a[1]≤a[2]≤. . . ≤ a[finalIndex] If the value is found, its index is returned If the value is not found, -1 is returned Note: Each execution of the recursive method reduces the search space by about a half © 2006 Pearson Addison-Wesley. All rights reserved

6 Binary Search An algorithm to solve this task looks at the middle of the array or array segment first If the value looked for is smaller than the value in the middle of the array Then the second half of the array or array segment can be ignored This strategy is then applied to the first half of the array or array segment © 2006 Pearson Addison-Wesley. All rights reserved

7 Binary Search If the value looked for is larger than the value in the middle of the array or array segment Then the first half of the array or array segment can be ignored This strategy is then applied to the second half of the array or array segment If the value looked for is at the middle of the array or array segment, then it has been found If the entire array (or array segment) has been searched in this way without finding the value, then it is not in the array © 2006 Pearson Addison-Wesley. All rights reserved

8 Pseudocode for Binary Search
© 2006 Pearson Addison-Wesley. All rights reserved

9 Recursive Method for Binary Search
© 2006 Pearson Addison-Wesley. All rights reserved

10 Execution of the Method search (Part 1 of 2)
© 2006 Pearson Addison-Wesley. All rights reserved

11 Execution of the Method search (Part 1 of 2)
© 2006 Pearson Addison-Wesley. All rights reserved

12 Linear Recursion Test for base cases. Recur once.
Begin by testing for a set of base cases (there should be at least one). Every possible chain of recursive calls must eventually reach a base case, and the handling of each base case should not use recursion. Recur once. Perform a single recursive call. (This recursive step may involve a test that decides which of several possible recursive calls to make, but it should ultimately choose to make just one of these calls each time we perform this step.) Define each possible recursive call so that it makes progress towards a base case.

13 A Simple Example of Linear Recursion
Example recursion trace: Algorithm LinearSum(A, n) { Input : A integer array A and an integer n such that A has at least n elements Output : The sum of the first n integers in A if ( n = 1) return A[0]; else return LinearSum(A, n - 1) + A[n - 1]; } LinearSum ( A , 5 ) 1 2 3 4 call return [ ] = + = 7 6 13 15 20

14 Output: 20 24-Feb-19 Computer Science Department

15 Reversing an Array Algorithm ReverseArray(A, i, j) { Input : An array A and nonnegative integer indices i and j Output : The reversal of the elements in A starting at index i and ending at j if (i < j ) swap A[i] and A[j]; ReverseArray(A, i + 1, j - 1); }

16 Output: 54321 24-Feb-19 Computer Science Department

17 Defining Arguments for Recursion
In creating recursive methods, it is important to define the methods in ways that facilitate recursion. This sometimes requires we define additional parameters that are passed to the method. For example, we defined the array reversal method as ReverseArray(A, i, j), not ReverseArray(A).

18 Computing Powers The power function, p(x,n)=xn, can be defined recursively: This leads to an power function that runs in O(n) time (for we make n recursive calls). We can do better than this, however.

19 Recursive Squaring We can derive a more efficient linearly recursive algorithm by using repeated squaring: For example, 24 = 2(4/2)2 = (24/2)2 = (22)2 = 42 = 16 25 = 21+(4/2)2 = 2(24/2)2 = 2(22)2 = 2(42) = 32 26 = 2(6/ 2)2 = (26/2)2 = (23)2 = 82 = 64 27 = 21+(6/2)2 = 2(26/2)2 = 2(23)2 = 2(82) = 128.

20 A Recursive Squaring Method
Algorithm Power(x, n) { Input : A number x and integer n = 0 Output : The value xn if (n = 0) return 1; if (n is odd ) { y = Power(x, (n - 1)/ 2); return x*y*y; } else { y = Power(x, n/ 2); return y*y; } }

21 Analyzing the Recursive Squaring Method
Algorithm Power(x, n) { Input : A number x and integer n = 0 Output : The value xn if (n = 0) return 1; if (n is odd ) { y = Power(x, (n - 1)/ 2); return x*y*y; } else { y = Power(x, n/ 2); return y*y; } } Each time we make a recursive call we halve the value of n; hence, we make log n recursive calls. That is, this method runs in O(log n) time. It is important that we used a variable twice here rather than calling the method twice.

22 Output: power of 3^4 =81 power of 5^5 =3125

23 Tail Recursion Tail recursion occurs when a linearly recursive method makes its recursive call as its last step. The array reversal method is an example. Such methods can be easily converted to non-recursive methods (which saves on some resources). Example: Algorithm IterativeReverseArray(A, i, j ) { Input : An array A and nonnegative integer indices i and j Output : The reversal of the elements in A starting at index i and ending at j while ( i < j ) { swap A[i] and A[j]; i = i + 1; j = j – 1; }

24 Binary Recursion Binary recursion occurs whenever there are two recursive calls for each non-base case.

25 Another Binary Recursive Method
Problem: add all the numbers in an integer array A: Algorithm BinarySum(A, i, n) { Input : An array A and integers i and n Output : The sum of the n integers in A starting at index i if (n = 1) return A[i]; return BinarySum(A, i, n/ 2) + BinarySum(A, i + n/ 2, n/ 2); } Example trace: 3 , 1 2 4 8 7 6 5

26 Output: 14 24-Feb-19 Computer Science Department

27 Computing Fibanacci Numbers
Fibonacci numbers are defined recursively: F0 = 0 F1 = 1 Fi = Fi¡1 + Fi¡2 for i > 1. As a recursive algorithm (first attempt): Algorithm BinaryFib(k) { Input : Nonnegative integer k Output : The kth Fibonacci number Fk if ( k <= 1) return k; else return BinaryFib(k - 1) + BinaryFib(k - 2); }

28 Analyzing the Binary Recursion Fibonacci Algorithm
Let nk denote number of recursive calls made by BinaryFib(k). Then n0 = 1 n1 = 1 n2 = n1 + n0 + 1 = = 3 n3 = n2 + n1 + 1 = = 5 n4 = n3 + n2 + 1 = = 9 n5 = n4 + n3 + 1 = = 15 n6 = n5 + n4 + 1 = = 25 n7 = n6 + n5 + 1 = = 41 n8 = n7 + n6 + 1 = = 67. Note that the value at least doubles for every other value of nk. That is, nk > 2k/2. It is exponential!

29 Output: fibonacci of 7 =13 fibonacci of 2 =1 24-Feb-19
Computer Science Department

30 A Better Fibonacci Algorithm
Use linear recursion instead: Algorithm LinearFibonacci(k): { Input : A nonnegative integer k Output : Pair of Fibonacci numbers (Fk, Fk-1) if ( k = 1) return (k, 0); else { (i, j) = LinearFibonacci(k - 1); return (i +j, i); } Runs in O(k) time.

31 References Chapter 3, Data Structures and Algorithms by Goodrich and Tamassia. Garbage Collection by Bill Venners (


Download ppt "Programming with Recursion"

Similar presentations


Ads by Google