720 likes | 870 Views
Chapter 14: Sorting and Searching. Objectives. After studying this chapter you should understand the following: orderings and the ordering of list elements; the simple sorting algorithms selection sort and bubble sort; how to generalize sort methods. the binary search algorithm.
E N D
Objectives • After studying this chapter you should understand the following: • orderings and the ordering of list elements; • the simple sorting algorithms selection sort and bubble sort; • how to generalize sort methods. • the binary search algorithm. • the notion of a loop invariant, and its role in reasoning about methods.
Objectives • Also, you should be able to: • trace a selection sort and bubble sort with a specific list of values; • sort a list by instantiating an ordering and using a predefined sort method; • trace a binary search with a specific list of values; • state and verify key loop invariants.
Ordering lists • To order a list, there must be an order on the element class. • We’ll assume • There is a boolean method inOrder defined for the class whose instances we want to order.
Ordering lists • Example: to order a List<Student> need • Thus if s1 and s2 are Student objects, • inOrder(s1,s2) true: s1 comes before s2. • inOrder(s1,s2) false: s1 need not come before s2. public boolean inOrder (Student first, Student second)
Ordering lists • Ordering alphabetically by name, inOrder(s1,s2) is true if s1’s name preceded s2’s name lexicographically. • Ordering by decreasing grade, inOrder(s1,s2) is true if s1’s grade was greater than s2’s.
Order properties • We write • s1 < s2 when inOrder(s1,s2) == true • s1 >= s2 when inOrder(s1,s2)== false • An ordering is antisymmetric: it cannot be the case that both s1<s2 and s2<s1. • An ordering is transitive. That is, if s1<s2 and s2<s3 for objects s1, s2, and s3, then s1<s3.
Order properties • Equivalence of objects: neither inOrder(s1,s2) nor inOrder(s2,s1) is true for objects s1 and s2. • Two equivalent objects do not have to be equal.
Ordered list • A list is ordered: • s1<s2, thens1 comes before s2 on the list: • Or for all indexes i, j: inOrder(list.get(i),list.get(j)) implies i < j. for all indexes i and j,i<j implies!inOrder(list.get(j),list.get(i)).
Selection Sort • Design: • Find the smallest element in the list, and put it in as first. • Find the second smallest and put it as second, etc.
Selection Sort (cont.) • Find the smallest. • Interchange it with the first. • Find the next smallest. • Interchange it with the second.
Selection Sort (cont.) • Find the next smallest. • Interchange it with the third. • Find the next smallest. • Interchange it with the fourth.
Selection sort • To interchange items, we must store one of the variables temporarily. • While making list.get(0) refer to list.get(2), • loose reference to original entry referenced by list.get(0).
Selection sort algorithm /** * Sort the specified List<Student> using selection sort. * @ensure * for all indexes i, j: * inOrder(list.get(i),list.get(j)) implies i < j. */ publicvoid sort (List<Student> list) { int first; // index of first element to consider on this step int last; // index of last element to consider on this step int small; // index of smallest of list.get(first)...list.get(last) last = list.size() - 1; first = 0; while (first < last) { small = smallestOf(list,first,last); interchange(list,first,small); first = first+1; } }
Selection sort algorithm /** * Index of the smallest of * list.get(first) through list.get(last) */ privateint smallestOf (List<Student> list, int first, int last) { int next; // index of next element to examine. int small; // index of the smallest of get(first)...get(next-1) small = first; next = first+1; while (next <= last) { if (inOrder(list.get(next),list.get(small))) small = next; next = next+1; } return small; }
Selection sort algorithm /** * Interchange list.get(i) and list.get(j) * require * 0 <= i < list.size() && 0 <= j < list.size() * ensure * list.old.get(i) == list.get(j) * list.old.get(j) == list.get(i) */ privatevoid interchange (List<Student> list, int i, int j) { Student temp = list.get(i); list.set(i, list.get(j)); list.set(j, temp); }
Analysis of Selection sort • If there are n elements in the list, the outer loop is performed n-1 times. The inner loop is performed n-first times. i.e. time= 1, n-1 times; time=2, n-2 times; … time=n-2, 1 times. • (n-1)x(n-first) = (n-1)+(n-2)+…+2+1 = (n2-n)/2 • As n increases, the time to sort the list goes up by this factor (order n2).
Bubble sort • Make a pass through the list comparing pairs of adjacent elements. • If the pair is not properly ordered, interchange them. • At the end of the first pass, the last element will be in its proper place. • Continue making passes through the list until all the elements are in place.
Pass 3 Pass 4
Bubble sort algorithm // Sort specified List<Student> using bubble sort. publicvoid sort (List<Student> list) { int last; // index of last element to position on this pass last = list.size() - 1; while (last > 0) { makePassTo(list, last); last = last-1; } } // Make a pass through the list, bubbling an element to position last. privatevoid makePassTo (List<Student> list, int last) { int next; // index of next pair to examine. next = 0; while (next < last) { if (inOrder(list.get(next+1),list.get(next))) interchange(list, next, next+1); next = next+1; } }
Fine-tuning bubble sort algorithm • Making pass through list no elements interchanged then the list is ordered. • If list is ordered or nearly so to start with, can complete sort in fewer than n-1 passes. • With mostly ordered lists, keep track of whether or not any elements have been interchanged in a pass.
Generalizing the sort methods • Sorting algorithms are independent of: • the method inOrder, as long as it satisfies ordering requirements. • The elements in the list being sorted.
Generalizing the sort methods • Want to generalize the sort to List<Element> instances with the following specification: • Thus: • Need to learn about generic methods. • Need to make the inOrder method part of a class. public <Element> void selectionSort ( List<Element> list, Order<Element> order)
Generic methods • Can define a method with types as parameters. • Method type parameters are enclosed in angles and appear before the return type in the method heading.
Generic methods • In the method definition: Method type parameter • swap is now a generic method: it can swap to list entries of any given type. public <Element> void swap (List<Element> list, int i, int j) { Element temp = list.get(i); list.set(i,list.get(j)); list.set(j,temp); }
Generic swap • When swap is invoked, first argument will be a List of some type of element, and local variable temp will be of that type. • No special syntax required to invoke a generic method. • When swap is invoked, the type to be used for the type parameter is inferred from the arguments.
Generic swap • For example, if roll is a List<Student>, List<Student> roll = … • And the method swap is invoked as swap(roll,0,1); • Type parameter Element is Student, inferred from roll. • The local variable temp will be of type Student.
inOrder as function object • Wrap up method inOrder in an object to pass it as an argument to sort. • Define an interface • A concrete order will implement this interface for some particular Element. /** * transitive, and anti-symmetric order on Element instances */ publicinterface Order<Element> { boolean inOrder (Element e1, Element e2); }
Implementing Order interface • To sort a list of Student by grade, define a class (GradeOrder) implementing the interface, and then instantiated the class to obtain the required object. //Order Students by decreasing finalGrade class GradeOrder implements Order<Student> { publicboolean inOrder (Student s1, Student s2) { return s1.finalGrade() > s2.finalGrade(); } }
Anonymous classes • Define the class and instantiate it in one expression. • For example, • This expression • defines an anonymous class implementing interface Order<Student>, and • creates an instance of the class. new Order<Student>() { boolean inOrder(Student s1, Student s2) { return s1.finalGrade() > s2.finalGrade(); } }
Generalizing sort using generic methods • Generalized sort methods have both a list and an order as parameters. publicclass Sorts { publicstatic <Element> void selectionSort ( List<Element> list, Order<Element> order) {…} publicstatic <Element> void bubbleSort ( List<Element> list, Order<Element> order) {… } }
Generalizing sort using generic methods • The order also gets passed to auxiliary methods. The selection sort auxiliary method smallestOf will be defined as follows: privatestatic <Element> int smallestOf ( List<Element> list, int first, int last, Order<Element> order ) {…}
Sorting a roll by grade • If roll is a List<Student>, to sort it invoke: • Or, using anonymous classes: Sorts.selectionSort(roll, new GradeOrder()); Sorts.selectionSort(roll, new Order<Student>() { boolean inOrder(Student s1, Student s2) { return s1.finalGrade() > s2.finalGrade(); } } );
Sorts as generic objects • wrap sort algorithm and ordering in the same object. • Define interface Sorter : //A sorter for a List<Element>. publicinterface Sorter<Element> { //e1 precedes e2 in the sort ordering. publicboolean inOrder (Element e1, Element e2); //Sort specified List<Element> according to this.inOrder. publicvoid sort (List<Element> list); }
Sorts as generic objects • Provide specific sort algorithms in abstract classes, leaving the ordering abstract. public abstract class SelectionSorter<Element> implements Sorter<Element> { // Sort the specified List<Element> using selection sort. public void sort (List<Element> list) { … } } Selection sort algorithm
Sorts as generic objects • To create a concrete Sorter, we extend the abstract class and furnish the order: class GradeSorter extends SelectionSorter<Student> { publicboolean inOrder (Student s1, Student s2){ return s1.finalGrade() > s2.finalGrade(); } }
Sorts as generic objects • Instantiate the class to get an object that can sort: • Using an anonymous class, GradeSorter gradeSorter = new GradeSorter(); gradeSorter.sort(roll); SelectionSorter<Student> gradeSorter = new SelectionSorter<Student>() { publicboolean inOrder (Student s1, Student s2){ return s1.finalGrade() > s2.finalGrade(); } }; gradeSorter.sort(roll);
Ordered Lists • Typically need to maintain lists in specific order. • We treat ordered and unordered lists in different ways. • may add an element to the end of an unordered list but want to put the element in the “right place” when adding to an ordered list. • Interface OrderedList ( does not extend List) public interface OrderedList<Element> A finite ordered list.
Ordered Lists • OrderedList shares features from List, but does not include those that may break the ordering, such as • public void add(int index, Element element); • public void set( List<Element> element, int i, int j); • OrderedList invariant: • for all indexes i, j:ordering().inOrder(get(i),get(j)) implies i < j. • OrderedList add method is specified as: publicvoid add (Element element) Add the specified element to the proper place in this OrderedList.
Binary Search • Assumes an ordered list. • Look for an item in a list by first looking at the middle element of the list. • Eliminate half the list. • Repeat the process.
Binary Search for 42 list.get(7) < 42 No need to look below 8 list.get(11) > 42 No need to look above 10 list.get(9)<42 No need to look below 10 Down to one element, at position 10; this isn’t what we’re looking for, so we can conclude that 42 is not in the list.
Generic search method itemIndex private <Element> int itemIndex (Element item, List<Element> list, Order<Element> order) Proper place for item on list found using binary search. require:list is sorted according to order. ensure:0 <= result && result <= list.size()for all indexes i: i < result implies order.inOrder(list.get(i),item)for all indexes i: i >= result implies !order.inOrder(list.get(i),item) • It returns an index such that • all elements prior to that index are smaller than item searched for, and • all of items from the index to end of list are not.
Implementation of itemIndex private <Element> int itemIndex (Element item, List<Element> list, Order<Element> order) { int low; // the lowest index being examined int high; // the highest index begin examined // for all indexes i: i < low implies order.inOrder(list.get(i),item) // for all indexes i: i > high implies !order.inOrder(list.get(i),item) int mid; // the middle item between low and high. mid == (low+high)/2 low = 0; high = list.size() - 1; while (low <= high) { mid = (low+high)/2; if (order.inOrder(list.get(mid),item)) low = mid+1; else high = mid-1; } return low; }
low high item 42 low 0 high 14 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mid ? (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) Searching for 42 in
item 42 low 8 high 14 s s s s s s s 28 ? ? ? ? ? ? ? mid 7? (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) low Searching for 42 high
item 42 low 8 high 10 s s s s s s s 28 ? ? ? 56 g g g high mid 11 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) low Searching for 42
item 42 low 8 high 10 s s s s s s s 28 s 33 ? 56 g g g high mid 10 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) Searching for 42 low
item 42 low 11 high 10 s s s s s s s 28 s 33 40 56 g g g high mid 10 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) Searching for 42 low 42 is not found using itemIndex algorithm