1 / 23

Intro to CS – Honors I Recursion

Intro to CS – Honors I Recursion. Georgios Portokalidis gportoka@stevens.edu. What is Recursion?. Define a process, data, algorithm, etc. in terms of itself Example in math: the sum of n numbers ∑ n = a 0 + a 1 + … a n or ∑ i = 0 ..n = a i

maya
Download Presentation

Intro to CS – Honors I Recursion

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Intro to CS – Honors IRecursion Georgios Portokalidis gportoka@stevens.edu

  2. What is Recursion? • Define a process, data, algorithm, etc. in terms of itself • Example in math: the sum of n numbers ∑n = a0 + a1 + … an or ∑i=0..n= ai • Recursively the sum function builds on itself ∑i=0..n = a0 + ∑i=1..n • Example in programming languages: a method can invoke itself like any other method

  3. Algorithms Where Recursion is Useful • Many search algorithms can be easily expressed using recursion • Example: searching for a name in the phonebook • Open the phonebook in the middle • Did we find the name?  Lucky! • Is the name alphabetically before that page?  Repeat the process with the first half of the phonebook • Is the name alphabetically after that page?  Repeat the process with the second half of the phonebook • The last steps involve subtasks that are a small version of the entire algorithm  Appropriate for recursion

  4. A Simple Example • Countdown from a number to 1 and then print a newline character • We already know how to do this using loops, but try to use recursion to achieve the same goal • Example: n=3  321\n • How would you complete countdown() using recursion? Not properly ending recursion can result in infinite recursion void countdown(int from) { if (from <= 0) System.out.println(); } Start with the end condition. There must always be an end condition.

  5. Why Recursion is Possible? • Every time we invoke a method it gets a new version of its parameters • The callee (i.e., the method calling) waits until the method called returns • The above two are not different when we use recursion, thus enabling it • But, where are the method arguments stored each time?

  6. Memory Organization of Program • Every program usually has 3 different memory areas to store data • Note that all this areas are in the same memory, the different is in their organization and intended use • The heap is used to store dynamically allocated data (stuff allocated using new), such as object instance variables • The data segment is used to store static variables, like class variables and constants. I.e.,the “globals” of the program • The stack is used to store data related with method invocation, like method arguments and local variables

  7. The Stack • A stack refers to placing one item on top of the other • A stack data structure follows last-in, first-out semantics

  8. Java’s Activation Stack

  9. Keys to Successful Recursion • A definition of a method that includes a recursive invocation of the method itself will not behave correctly unless you follow some specific design guidelines. The following rules apply to most cases that involve recursion: • The heart of the method definition must be an if-else statement or some other branching statement that leads to different cases, depending on some property of a parameter of the method • One or more of the branches should include a recursive invocation of the method. These recursive invocations must, in some sense, use “smaller” arguments or solve “smaller” versions of the task performed by the method • One or more branches must include no recursive invocations. These branches are the base cases, or stopping cases • One common way to ensure that your stop case is reached is to make recursive invocations of your method use a “smaller” argument

  10. StackOverflowError • Can it be caught? • Should you use it to “fix” bugs in your code? • A StackOverflowError is thrown to notify the user/programmer that the stack was exhausted! • It can be caught, but you can’t fix it! • You can increase the size of the stack the VM is using when launching a program • Example: from the command line java -Xss... • java –Xss4m MyProg

  11. From Recursion to Iterative Execution • Any method definition that includes a recursive call can be rewritten, so that it accomplishes the same task without recursion • Recursion can be wasteful • That is usually accomplished by using a loop • Frequently also some additional variables • A non-recursive repetitive process is called iteration • The method implementing it is called an iterative method void countdown(int from) { for (inti = from; i >= 0; i++) System.out.print(i); System.out.println(); } Writing countdown without recursion

  12. Recursive Methods Returning a Value • The Fibonacci sequence: Fn= Fn-1 + Fn-2, where F0 = 0 and F1 = 1 • Let’s start with the stop cases intfibonacci(int n) { if (n == 0) return 0; if (n == 1) return n; … }

  13. Generic Search • The simplest way to search an array for an item (i.e., check that an item is present) in the array is to iterate over all of its elements • public intfindItem(int[] myArray, int item) • { • int found = -1; • for (inti = 0; i < myArray.length; i++) • { • if (item == myArray[i]) • { • found = i; • break; • } • } • return found; • } Time to complete is linear to the size of the array. If it contains n items, worst case is n comparisons  O(n) Not the fastest way

  14. Searching Over Sorted Items • If an array is sorted (a[0] ≤ a[1] ≤ a[2] ≤...≤ a[a.length–1]) we can do better • Because we have an idea what kind of items are before and after an item we are examining • Example: assume a[5] == 7, then 7 <= a[5] <= a[i] for i>= 5 • Algorithm to search a sorted array for an item • m = a random index between 0 and (a.length - 1) • if (target == a[m]) • return m; • else if (target < a[m]) • return the result of searching a[0] through a[m - 1] • else if (target > a[m]) • return the result of searching a[m + 1] through a[a.length - 1] The if-else statement breaks the array in two parts Not the fastest way

  15. Binary Search • Binary search involves picking the item m in the following algorithm to be the midpoint between 0 and (length - 1) • Example: assume a.length == 7, m = 3 or m = 4 • Algorithm to search a sorted array for an item • m = approximate midpoint between 0 and (a.length - 1) • if (target == a[m]) • return m; • else if (target < a[m]) • return the result of searching a[0] through a[m - 1] • else if (target > a[m]) • return the result of searching a[m + 1] through a[a.length - 1] Can we use this algorithm with recursion as is? The if-else statement breaks the array in two (almost) equally sized parts

  16. Binary Search Using Recursion • To make our algorithm appropriate for recursion we need to generalize it a bit • It already includes a task that is a smaller version of the whole task • Algorithm to search a[first] through [last] of a sorted array for an item • m = approximate midpoint between first and last • if (target == a[m]) • return m; • else if (target < a[m]) • return the result of searching a[first] through a[m - 1] • else if (target > a[m]) • return the result of searching a[m + 1] through a[last] Another problem remains. Can you spot it?

  17. Final Binary Search Using Recursion • To make our algorithm appropriate for recursion we need to generalize it a bit • It already includes a task that is a smaller version of the whole task • Algorithm to search a[first] through [last] of a sorted array for an item • m = approximate midpoint between first and last • if (first > last) • return -1; • else if (target == a[m]) • return m; • else if (target < a[m]) • return the result of searching a[first] through a[m - 1] • else if (target > a[m]) • return the result of searching a[m + 1] through a[last]

  18. Binary Search Algorithm Visualization • http://www.dave-reed.com/book/Chapter8/search.html

  19. Iterative Binary Search • m = approximate midpoint between first and last • if (target == a[m]) • return m; • else if (target < a[m]) • last = m – 1; • else if (target > a[m]) • first = m + 1; • Repeat while first < last • return -1; Recursive algorithm • m = approximate midpoint between first and last • if (first > last) • return -1; • else if (target == a[m]) • return m; • else if (target < a[m]) • return the result of searching a[first] through a[m - 1] • else if (target > a[m]) • return the result of searching a[m + 1] through a[last]

  20. Iterative Binary Search int first = 0, last = a.length -1, m; while (first < last) { // calculate the midpoint for roughly equal partition m = midpoint(first, last); // determine which subarray to search if (target > a[m]) // change last index to search lower subarray last = m - 1; else if (target < a[m]) // change lower index to search upper subarray first= m + 1; else // we do not need to check m == target // key found at index m return m; } // key not found return -1; } • m = approximate midpoint between first and last • if (target == a[m]) • return m; • else if (target < a[m]) • last = m – 1; • else if (target > a[m]) • first = m + 1; • Repeat while first < last • return -1;

  21. int first = 0, last = a.length -1, m; while (first < last) { // calculate the midpoint for roughly equal partition m = midpoint(first, last); // determine which subarray to search if (target > a[m]) // change last index to search lower subarray last = m - 1; else // change lower index to search upper subarray first = m + 1; } // postcondition at exit of loop // if target in a, then first == last, else first > last // Deferred equality test if (first == last && a[first] == target) return first; else // key not found return -1; } Optimizations • Performing branches within loops can be costly

  22. Complexity of Binary Search • For an array with n elements, if we find the target in the first iteration, we check 1 element • Otherwise, if the length of the array is • odd, the array is split to segments of (n-1)/2 length • even, the array is split into a (n/2)-1 and a (n/2) segment • Worst case is x iterations • If the length of the array is even 2x = n • If the length of the array is odd 2x < n • 2x <= n  log2(2x) <= log2(n)  x <= log2(n) • Complexity is O(log2(n))

  23. (Advanced) Issues with Binary Search • Reduced cache performance due to bad locality • Leeds to serial search being more effective on small datasets • The array must be sorted, so you need to take into account the time sort an array that it is not • Separate “keys” from actual data being searched • Take care of your bounds • Are they inclusive or exclusive • Be consistent • Can your array hold multiple items with the same value? • If yes, do you need to return all of them, the first, any, …? • Java offers a set of overloaded binarySearch() static methods in the class Arrays in the standard java.util package for performing binary searches • Must be arrays of primitives, or objects that implement the Comparable interface

More Related