Review for Final Exam ICS 201 Recursion Recursive void Methods A recursive method is a method that includes a call to itself Recursion is based on the general problem solving technique of breaking down a task into subtasks In particular, recursion can be used whenever one subtask is a smaller version of the original task Execution of writeVertical(123) Execution of writeVertical(12) Execution of writeVertical(1) Completion of writeVertical(12) Completion of writeVertical(123) General Form of a Recursive Method Definition The general outline of a successful recursive method definition is as follows: One or more cases that include no recursive calls: base cases or stopping cases One or more cases that include one or more recursive calls to the method being defined These recursive calls should solve "smaller" versions of the task performed by the method being defined They must come closer to the base case. Recursion Versus Iteration Recursion is not absolutely necessary Any task that can be done using recursion can also be done in a nonrecursive manner A nonrecursive version of a method is called an iterative version An iteratively written method will typically use loops of some sort in place of recursion A recursively written method can be simpler, but will usually run slower and use more storage than an equivalent iterative version The Recursive Method power Searching Searching an array of Strings Searching an array of Strings is just like searching an array of integers, except Instead of i1==i2 we need to use s1.equals(s2) static final int NONE = -1; // not a legal index static int linearSearch(String target, String[] a) { for (int p = 0; p < a.length; p++) { if (target.equals(a[p])) return p; } return NONE; } Binary search Linear search has linear time complexity: Time n if the item is not found Time n/2, on average, if the item is found If the array is sorted, we can write a faster search How do we look up a name in a phone book, or a word in a dictionary? Look somewhere in the middle Compare what’s there with the thing you’re looking for Decide which half of the remaining entries to look at Repeat until you find the correct place This is the binary search algorithm Binary search in Java static int binarySearch(Comparable target, Comparable[] a, int left, int right) { int l = left, r = right; while (l <= r) { int m = (l + r) / 2; int comp = target.compareTo(a[m]); if (comp == 0) return m; else if (comp < 0) r = m – 1; else /* comp > 0 */ l = m + 1; } return NONE; // As before, NONE = -1 } Recursive binary search in Java static int binarySearch(Comparable target, Comparable[] a, int left, int right) { if (left > right) return NONE; int m = (left + right) / 2; int comp = target.compareTo(a[m]); if (comp == 0) return m; else if (comp < 0) return binarySearch(target, a, left, m-1); else // comp > 0 return binarySearch(target, a, m+1, right); } Sorting Objectives To learn how to use the standard sorting methods in the Java API To learn how to implement the following sorting algorithms: selection sort, mergesort, and quicksort To understand the difference in performance of these algorithms, and which to use for small arrays, which to use for medium arrays, and which to use for large arrays Selection Sort Sorting: Arrange things into either ascending or descending order Task: rearrange books on shelf by height Shortest book on the left Approach: Look at books, select shortest book Swap with first book Look at remaining books, select shortest Swap with second book Repeat … Selection Sort in Java Merge Algorithm 1. 2. Access the first item from both sequences While not finished with either sequence Compare the current items from the two sequences, copy the smaller current item to the output sequence, and access the next item from the input sequence whose item was copied 3. 4. Copy any remaining items from the first sequence to the output sequence Copy any remaining items from the second sequence to the output sequence How merge sort works MergeSort in Java MergeSort in Java Quicksort Quicksort rearranges an array into two parts so that all the elements in the left subarray are less than or equal to a specified value, called the pivot Quicksort ensures that the elements in the right subarray are larger than the pivot Advantage: Disadvantage: No extra memory is needed Fast running time (in average) Unstable in running time Finding “pivot” element is a big issue! Partitioning A key step in the Quicksort algorithm is partitioning the array We choose some (any) number p in the array to use as a pivot We partition the array into three parts: p numbers less than p p numbers greater than or equal to p Example of Partitioning choose pivot: search: swap: search: swap: search: swap: search: 436924312189356 436924312189356 433924312189656 433924312189656 433124312989656 433124312989656 433122314989656 433122314989656 swap with pivot: 133122344989656 (left > right) Quick Sort in Java ArrayList The ArrayList Class ArrayList is a class in the standard Java libraries Unlike arrays, which have a fixed length once they have been created, an ArrayList is an object that can grow and shrink while your program is running In general, an ArrayList serves the same purpose as an array, except that an ArrayList can change length while the program is running Using the ArrayList Class An initial capacity can be specified when creating an ArrayList as well The following code creates an ArrayList that stores objects of the base type String with an initial capacity of 20 items ArrayList<String> list = new ArrayList<String>(20); Specifying an initial capacity does not limit the size to which an ArrayList can eventually grow Note that the base type of an ArrayList is specified as a type parameter Methods in the Class ArrayList The tools for manipulating arrays consist only of the square brackets and the instance variable length ArrayLists, however, come with a selection of powerful methods that can do many of the things for which code would have to be written in order to do them using arrays The "For Each" Loop The ArrayList class is an example of a collection class Starting with version 5.0, Java has added a new kind of for loop called a for-each or enhanced for loop This kind of loop has been designed to cycle through all the elements in a collection (like an ArrayList) A for-each Loop Used with an ArrayList Generics Introduction to Generics Beginning with version 5.0, Java allows class and method definitions that include parameters for types Such definitions are called generics Generic programming with a type parameter enables code to be written that applies to any class Generics A class definition with a type parameter is stored in a file and compiled just like any other class Once a parameterized class is compiled, it can be used like any other class However, the class type plugged in for the type parameter must be specified before it can be used in a program Doing this is said to instantiate the generic class Sample<String> object = new Sample<String>(); A Class Definition with a Type Parameter Class Definition with a Type Parameter A class that is defined with a parameter for a type is called a generic class or a parameterized class The type parameter is included in angular brackets after the class name in the class definition heading Any non-keyword identifier can be used for the type parameter, but by convention, the parameter starts with an uppercase letter The type parameter can be used like other types used in the definition of a class Collections Collections A Java collection is any class that holds objects and implements the Collection interface For example, the ArrayList<T> class is a Java collection class, and implements all the methods in the Collection interface Collections are used along with iterators The Collection interface is the highest level of Java's framework for collection classes All of the collection classes discussed here can be found in package java.util The Collection Landscape The Collection Framework The Collection<T> interface describes the basic operations that all collection classes should implement The method headings for these operations are shown on the next several slides Since an interface is a type, any method can be defined with a parameter of type Collection<T> That parameter can be filled with an argument that is an object of any class in the collection framework Collection Interface methods Collection Relationships There are a number of different predefined classes that implement the Collection<T> interface Programmer defined classes can implement it also A method written to manipulate a parameter of type Collection<T> will work for all of these classes, either singly or intermixed There are two main interfaces that extend the Collection<T> interface: The Set<T> interface and the List<T> interface Collection Relationships Classes that implement the Set<T> interface do not allow an element in the class to occur more than once The Set<T> interface has the same method headings as the Collection<T> interface, but in some cases the semantics (intended meanings) are different Methods that are optional in the Collection<T> interface are required in the Set<T> interface Collection Relationships Classes that implement the List<T> interface have their elements ordered as on a list Elements are indexed starting with zero A class that implements the List<T> interface allows elements to occur more than once The List<T> interface has more method headings than the Collection<T> interface Some of the methods inherited from the Collection<T> interface have different semantics in the List<T> interface The ArrayList<T> class implements the List<T> interface The Collections Class The Collections class is a utility class. It contains static methods for manipulating collection objects. The Arrays class is also a utility class. It contains static methods for manipulating arrays. One useful method used is asList() to convert an array into a list. The following are the most frequently used methods of the Collections class. static static static static static static static static int binarySearch(List list, Object o) int binarySearch(List list, Object o, Comparator c) void sort(List list) void sort(List list, Comparator c) Object max(Collection c) Object min(Collection c) void reverse(List list) void shuffle(List list) Iterators Iterators An iterator is an object that is used with a collection to provide sequential access to the collection elements This access allows examination and possible modification of the elements An iterator imposes an ordering on the elements of a collection even if the collection itself does not impose any order on the elements it contains If the collection does impose an ordering on its elements, then the iterator will use the same ordering The Iterator<T> Interface Java provides an Iterator<T> interface Any object of any class that satisfies the Iterator<T> interface is an Iterator<T> An Iterator<T> does not stand on its own It must be associated with some collection object using the method iterator If c is an instance of a collection class (e.g., Vector<String>), the following obtains an iterator for c: Iterator iteratorForC = c.iterator(); The ListIterator<T> Interface The ListIterator<T> interface extends the Iterator<T> interface, and is designed to work with collections that satisfy the List<T> interface A ListIterator<T> has all the methods that an Iterator<T> has, plus additional methods A ListIterator<T> can move in either direction along a list of elements A ListIterator<T> has methods, such as set and add, that can be used to modify elements Iterator methods ListIterator methods