370 likes | 493 Views
Searching & Sorting. 12. 7. 14. 22. 5. 18. 40. Components in a Search:. List of Comparable Items : . A =. key Item: . key = 5. 12. 7. 14. 22. 5. 18. 40. A =. key. key. key. key. key. key. key = 18. Linear Search:.
E N D
12 7 14 22 5 18 40 Components in a Search: List of Comparable Items: A = key Item: key = 5
12 7 14 22 5 18 40 A = key key key key key key key = 18 Linear Search: 0 1 2 3 4 5 6 index key == a[5]? key == a[0]? key == a[1]? key == a[2]? key == a[3]? key == a[4]? Done!
Linear Search: publicboolean linearSearch(int [ ] aList, int size, int key){ boolean found = false; int index = 0; while(!found && (index < size)) if (key == aList[i]) found = true; else index++; return found; };
key is at A[0] key is at A[size-1] OR not found key can appear in each of the n index positions with equal probability Algorithm Analysis: Number of compares: Best Case Analysis: 1 Worst Case Analysis: n Average Case Analysis: (n + 1)/2
Algorithm Analysis: 12 7 14 22 5 18 40 A = Algorithm Analysis: Average Case Analysis: (n + 1)/2 # of Comparisons: 1 2 3 . . . Probability 1/7 1/7 1/7 . . . . . . Contributions 1 * 1/7 2 * 1/7 3 * 1/7
key key key Binary Search: Ordered! aList = 12 17 24 32 35 48 50 57 key = = aList[mid] ? key = 24 Done!
public static boolean binarySearch(int [ ]a, int first, int last, int key){ int index = -1; if (first > last) return false; else { index = (first + last)/2; if (key = = a[index]) return true; else if (key < a[index]) return binarySearch(a, first, index -1, key); else return binarySearch(a, index + 1, last, key); } //end else } //end binarySearch
Sorting Algorithms • Bubble Sort • Insertion Sort • Quicksort • Merge Sort
i A high low Bubble Sort Strategy: During each iteration move the greatest remaining element to the back of the list. At some intermediate stage of the execution of this algorithm, the array to be sorted, call it A, will have the following properties: front segment back segment sorted in ascending order unsorted every element in the back segment is greater than or equal to every element in the front segment. Goal: Sort list of integers in the range of indices low<= i < high in ascending order
j j i A high low Bubble Sort Strategy: During each iteration move the greatest remaining element to the back of the unsorted list (front segment). Compare A[j] with A[j+1] and swap if A[j] > A[j+1] An intermediate stage picture shows i front segment front segment middle segment back segment sorted in ascending order Every element is less than or equal to A[j] unsorted When j = i – 1, the greatest element in the front segment is at index j every element in the back segment is greater than or equal to every element in the front segment Decrement i and the statements about the back segment remain true Goal: Sort list of integers in the range of indices low<= i < high in ascending order Goal: Move largest remaining integer to the back of the front segment
A swap has occurred, continue the sort for another iteration of i public static void bubbleSort(int a[], int low, int high){ boolean sorted = false; for (int i = high; (i > 0) && !sorted; i-- ){ sorted = true; for (int j = low; j < i - 1; j++){ if (a[ j ] > a[ j+1]){ int temp = a[ j ]; a[ j ] = a[ j+1 ]; a[ j+ 1] = temp; sorted = false; } //end if } //end for } //end bubbleSort End the search when no exchanges are needed
3 3 3 3 3 3 3 3 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 15 15 15 15 15 15 15 45 40 40 3 40 40 40 40 3 40 40 40 40 40 40 40 3 40 3 40 3 40 3 3 40 40 3 45 45 45 45 45 45 45 15 22 22 15 22 15 22 22 22 22 22 22 3 15 3 15 3 15 3 3 22 3 22 15 15 3 40 40 40 40 40 40 40 40 40 15 40 40 3 22 40 15 15 40 15 3 40 40 15 15 15 15 15 15 15 15 15 40 15 15 15 8 8 8 8 22 22 22 22 22 22 22 14 22 22 22 22 22 22 22 22 14 3 22 22 15 14 15 14 14 22 14 3 15 14 12 12 12 22 8 8 8 8 12 14 14 14 14 12 8 12 14 14 14 8 3 14 12 3 14 14 8 14 12 14 14 14 8 14 5 5 22 12 12 12 12 12 8 14 12 12 12 8 8 3 12 8 8 8 12 3 8 12 8 12 12 12 8 12 12 12 8 12 22 22 5 5 5 5 5 5 8 14 8 8 8 5 8 5 5 12 12 8 8 8 3 12 8 12 8 12 12 12 12 8 3 8 14 14 14 14 14 14 14 14 5 5 5 5 5 5 5 5 5 5 5 3 5 5 5 5 5 5 5 14 14 5 5 5 5 5 Bubble Sort in Action
low i i high A: temp Insertion Sort Insertion sort is the strategy used by the card player who picks up the card he or she is dealt one at a time and inserts it into his or her existing hand Strategy: put the element, call it x, at index i into its proper place in the front segment A snapshot of the algorithm at an intermediate stage: j j j front segment x x back segment 1. Copy A[i] into local variable temp sorted in ascending order unsorted, some elements in the back segment may be less than some (or all) elements in the front segment This creates a “hole” at index i 2. Set index j = i - 1 x 3. while(temp < A[j]) A[j+1] = A[j]; Implementation of this algorithm is left as an exercise. This effectively moves the “hole” left 4. Found place for x. A[j] = temp 5. Increment i – front segment grows by 1
high i low A: Quicksort Partition the array between indices low and high – select a pivot and move all values that are less than or equal to the pivot to the left of the pivot index and all values greater than the pivot to the right of the pivot index. • Step 1 – randomly choose a pivot index between low and high. Alternatively select low as the pivot index. (It is as good as any choice) • Step 2 – move the pivot to position A[low] • Step 3 – set partition indices i = low + 1, j = high - 1 j Pivot
high i i j i j low A: Quicksort • Step 4a – while( A[i] <= A[low]) i++; //move pivot index i to right • Step 4b – while(A[j] > A[low]) j--; //move pivot index j to the left • Step 5 – swap A[i] and A[j] • Repeat Steps 4a, 4b, and 5 until i > j //(unprocessed segment is empty) • Step 6 – swap A[low] and A[j] //move pivot to back of front seg. j pivot Pivot x y y x All entries greater than the pivot All entries less than or equal to the pivot unprocessed
i i i i i j j j i j 21 10 17 10 21 47 Partition j j high low A: 17 10 21 24 19 6 47 44 10 24 19 41 25 int i = low + 1; swap(A[low], A[j]); Randomly select index greater than or equal to low less than high as the pivotIndex. int j = high –1; while (i < = j) { swap A[low] and A[pivotIndex] while ((i <= j) && (A[i] <= A[low])) i++; while (A[j] > A[low]) j--; if (i < j) swap(A[i], A[j]); }
high low pivot entries <= pivot entries > pivot The high index is “off right” Quicksort When a call to partition terminates, the pivot separates all the entries that are less than or equal to the pivot from those entries greater than the pivot. quickSort front segment quickSort back segment public static void quickSort (int [ ] A, int low, int high) { if (high – low >= 2) { pivotIndex = partition (A, low, high); quickSort (A, low, pivotIndex); quickSort (A, pivotIndex + 1, high); }
Quicksort first call 2nd call 3rd call Each time the (sub) list is partitioned exactly one value (the pivot) is placed in its correct position. If the list is equally divided during each partitioning, it will require about lg (n) calls to quickSort to produce a sorted list.
Quicksort Analysis of the performance of quickSort – assume a list of size N Count the (approximate) number of compares needed to sort the list. Best case: Each pivot divides the remaining list in half lg N Number of recursive calls: Number of compares : < N during each level of recursion Worst case: Each pivot is at the front or back of the list N - 1 Number of recursive calls: Number of compares: < N during each level of recursion Average case: < c lg N, for some constant c Number of recursive calls: Number of compares: < N during each level of recursion
Merge Sort Strategy: Recursively split the list in half and merge the the two returned segments.
A = 12 16 25 27 5 14 15 29 12 16 25 27 5 14 15 29 12 16 25 27 5 14 15 29 12 16 25 27 5 14 15 29 5 14 15 29 25 27 12 16 12 16 25 27 5 14 15 29 5 12 14 15 16 25 27 29 split merge
last first A = 12 16 25 27 5 14 15 29 B = 5 12 14 15 16 25 27 29 next if (A[first] <= A[last]) B[next] = A[first]; first++; else B[next] = A[last]; last++; Merge Process
first middle last public static void mergeSort (int [ ] A, int first, int last) { if (last – first > 1) { int middle = (first + last)/2; mergeSort(A, first, middle); mergeSort (A, middle, last); merge (A, first, middle, last); } } The terminal index is “off right”.
Merge the two halves until one runs out Append the remaining elements to the end of tempArray Copy the contents of tempArray back into A privatestaticvoid merge( int [ ] A, int first, int mid, int last) { int [ ] tempArray = newint[last - first]; int i = first, j = middle, k; for (k = 0; i < middle && j < last; k++) if (A[i] <=A[j}) tempArray[k] = A[i++]; else tempArray[k] = A[j++]; for ( ; i < middle; k++) tempArray[k] = A[i++]; for ( ; j < last; k++) tempArray[k] = A[j++]; for (int index = 0; index < last - first; index++) A[first + index] = tempArray[iindex]; }
A = 12 16 25 27 5 14 15 29 12 16 25 27 5 14 15 29 12 16 25 27 5 14 15 29 12 16 25 27 5 14 15 29 Levels = ? log(n) + 1 Total Complexity = n(log(n) + 1) Work = ? n Number of compares at each level during merge
Shell Sort Strategy: set a gap (initially let gap = n/2), insertion sort elements separated by a distance of gap, reduce the gap by increments after each iteration until it is = 1, and continue.
gap = max(1, (int) gap /2) = 2 0 1 2 3 4 5 6 7 8 10 3 3 10 24 41 25 27 31 3 27 41 25 24 27 31 25 44 41 27 44 47 47 44 i i i i i i i i i i i i Shell Sort Example: an array of int, length n = 9 gap = n/2 = 4 1 A 24 31 44 27 10 47 41 3 25 for (int i = gap; i < A.length; i++) { int temp = A[i]; for ( ; j >= gap && temp < A[j-gap]; j -= gap) A[j] = A[j – gap]; A[j] = temp; }
public static <E extends Comparable<? super E>> void shellsort(E[ ] a) { for (int gap = a.length/2; gap > 0; gap = Math.max(1, (int)gap/2.2)) for (int i = gap; i < a.length; i++) { E temp = a[i]; int j = i; for( ; j >= gap && temp.compareTo(a[j-gap]) < 0; j-=gap) a[j] = a[j – gap]; a[j] temp; } } use gap = (int)gap/2.2 for the best performance
Constructing an ordered list We want our ordered list to be: • Generic – hold items of any class derived from Object • Resizable – able to expand to accommodate the need • Self-maintaining – order is preserved after insert and remove operations
Comparing two Objects Primitive types can be compared using the relational operators, but in Java operators cannot be overloaded by the application programmer. (And primitive types cannot be stored in our generic ordered list.) Suppose we wanted to hold objects of a class Person in an OrderedArray container that we are constructing. We must: • Declare that class Person implements Comparable • Implement the method compareTo that is in the Comparable interface OR • Provide a class PersonComparator that extends Comparator • Provide a constructor in class OrderedArray that takes a Comparator object as a parameter (if using Comparator)
Must cast object other to class Person Comparing Two Objects Consider a class Person publicclass Person implementsComparable { private String sirName; privateint age, weight, height; privatedouble salary; //constructors and other methods public int compareTo (Object other) { /**this method returns a negative number if this object is less than other, 0 if they are equal, and a + integer if this > other*/ /**choose sirName as the attribute to compare – String objects are themselves Comparable*/ return sirName.compareTo(((Person).other).sirName); } }
ADT OrderedList TYPES: Object, Integer, Boolean FUNCTIONS: Create: ( ) OrderedList Dissolve: OrderedList ( ) insert: OrderedList, Object OrderedList remove: OrderedList, Object -/-> OrderedList remove: OrderedList, Integer -/-> OrderedList, Object retrieve: OrderedList, Integer -/-> Object findIndex: OrderedList, Object Integer contains: OrderedList, Object Boolean isEmpty: OrderedList Boolean size: OrderedList Integer
Class OrderedList public class OrderedList { privateComparable [ ] buffer; privateint size, capacity; privatevoid resize( ) { /**add additional capacity to buffer when inserting into a full list*/ public OrderedList( ) { } //default constructor – create buffer of capacity 16 public OrderedList(int cap) { } //user specified initial capacity public void insert(Comparable theObject) { /**if full, resize – add an additional 16 spaces down cast theObject and store result in a local variable temp starting at size –1 compare each item in buffer with temp and move one place to the right if greater **see next sheet for details insert the contents of temp into buffer at index holding the “hole” */} (continued on following slides)
Need to compare 2 Person objects Use the compareTo() method of Person to order list elements Performing a Comparison Compare the ith buffer element with the contents of temp //temp contains (Person)theObject //inside of a iterative loop we perform the following comparison Person thisPerson = (Person)buffer[i]; if (thisPerson.compareTo(temp) > 0) { //move thisPerson one space to the right } else { //this is the index where theObject is placed }
Continuingdeclaration of OrderedList public void remove(Comparable theDumped) { /**preconditions: list not empty and list contains theDumped post-condition: first occurrence of theDumped is removed */ } public Comparable remove(int theIndex) { /**preconditions: list not empty and 0 <= theIndex < size post-condition: contents of buffer at theIndex is removed and returned*/ } public boolean contains(Comparable theTarget) { /**use down cast and method compareTo of Person to test if theTarget is found in buffer.*/ } public Comparable retrieve(int theIndex) { /**preconditions: list not empty and 0 <= theIndex < size post-condition: contents of buffer at theIndex is returned*/ }
Remaining methods publicint findIndex (Comparable target) { /**post-condition: returns index of first occurrence of target if found, else –1*/ publicboolean isEmpty( ) { } public int size( ) { } } //end of class declaration It is left as an exercise for you to implement class OrderedList as described in these overheads.