An Introduction to Programming and Object Oriented Design
An Introduction to Programming and Object Oriented Design using Java 2 nd Edition. May 2004 Jaime Niño Frederick Hosch 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. ñ the notion of a loop invariant, and its role in reasoning about methods. May 2004 NH-Chapter 14 2
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. May 2004 NH-Chapter 14 3
Ordering lists ñ To order a list, there must be an order on the element class. ñ We’ll assume ñ There is a boolean method in. Order defined for the class whose instances we want to order. May 2004 NH-Chapter 14 4
Ordering lists ñExample: to order a List<Student> need public boolean in. Order (Student first, Student second) ñ Thus if s 1 and s 2 are Student objects, ñ in. Order(s 1, s 2) true: s 1 comes before s 2. ñ in. Order(s 1, s 2) false: s 1 need not come before s 2. May 2004 NH-Chapter 14 5
Ordering lists ñ Ordering alphabetically by name, in. Order(s 1, s 2) is true if s 1’s name preceded s 2’s name lexicographically. ñ Ordering by decreasing grade, in. Order(s 1, s 2) is true if s 1’s grade was greater than s 2’s. May 2004 NH-Chapter 14 6
Order properties ñ We write ñ s 1 < s 2 when in. Order(s 1, s 2) == true ñ s 1 >= s 2 when in. Order(s 1, s 2)== false ñ An ordering is antisymmetric: it cannot be the case that both s 1 < s 2 and s 2 < s 1. ñ An ordering is transitive. That is, if s 1 < s 2 and s 2 < s 3 for objects s 1, s 2, and s 3, then s 1 < s 3. May 2004 NH-Chapter 14 7
Order properties ñ Equivalence of objects: neither in. Order(s 1, s 2) nor in. Order(s 2, s 1) is true for objects s 1 and s 2. ñ Two equivalent objects do not have to be equal. May 2004 NH-Chapter 14 8
Ordered list ñA list is ordered: ñs 1 < s 2, then s 1 comes before s 2 on the list: for all indexes i, j: in. Order(list. get(i), list. get(j)) implies i < j. ñ Or for all indexes i and j, i < j implies !in. Order(list. get(j), list. get(i)). May 2004 NH-Chapter 14 9
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. May 2004 NH-Chapter 14 10
Selection Sort (cont. ) ñ Find the smallest. ñ Interchange it with the first. ñ Find the next smallest. ñ Interchange it with the second. May 2004 NH-Chapter 14 11
Selection Sort (cont. ) ñ Find the next smallest. ñ Interchange it with the third. ñ Find the next smallest. ñ Interchange it with the fourth. May 2004 NH-Chapter 14 12
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). May 2004 NH-Chapter 14 13
Selection sort algorithm /** * Sort the specified List<Student> using selection sort. * @ensure * for all indexes i, j: * in. Order(list. get(i), list. get(j)) implies i < j. */ public void 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 = list. size() - 1; first = 0; while (first < last) { small = smallest. Of(list, first, last); interchange(list, first, small); first = first+1; } } May 2004 NH-Chapter 14 14
Selection sort algorithm /** * Index of the smallest of * list. get(first) through list. get(last) */ private int smallest. Of (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(nextsmall = first; next = first+1; while (next <= last) { if (in. Order(list. get(next), list. get(small))) small = next; next = next+1; } return small; } May 2004 NH-Chapter 14 15
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) */ private void interchange (List<Student> list, int i, int j) { Student temp = list. get(i); list. set(i, list. get(j)); list. set(j, temp); } May 2004 NH-Chapter 14 16
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 = (n 2 -n)/2 ñ As n increases, the time to sort the list goes up by this factor (order n 2). May 2004 NH-Chapter 14 17
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. May 2004 NH-Chapter 14 18
Pass 1 May 2004 NH-Chapter 14 19
Pass 2 May 2004 NH-Chapter 14 20
Pass 3 Pass 4 May 2004 NH-Chapter 14 21
Bubble sort algorithm // Sort specified List<Student> using bubble sort. public void sort (List<Student> list) { int last; // index of last element to position on this pass last = list. size() - 1; while (last > 0) { make. Pass. To(list, last); last = last-1; } } // Make a pass through the list, bubbling an element to position last. private void make. Pass. To (List<Student> list, int last) { int next; // index of next pair to examine. next = 0; while (next < last) { if (in. Order(list. get(next+1), list. get(next))) interchange(list, next+1); next = next+1; } } May 2004 NH-Chapter 14 22
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. May 2004 NH-Chapter 14 23
Generalizing the sort methods ñ Sorting algorithms are independent of: ñ the method in. Order, as long as it satisfies ordering requirements. ñ The elements in the list being sorted. May 2004 NH-Chapter 14 24
Generalizing the sort methods ñWant to generalize the sort to List<Element> instances with the following specification: public <Element> void selection. Sort ( List<Element> list, Order<Element> order) ñ Thus: ñ Need to learn about generic methods. ñ Need to make the in. Order method part of a class. May 2004 NH-Chapter 14 25
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. May 2004 NH-Chapter 14 26
Generic methods ñIn the method definition: Method type parameter 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); } ñ swap is now a generic method: it can swap to list entries of any given type. May 2004 NH-Chapter 14 27
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. May 2004 NH-Chapter 14 28
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. May 2004 NH-Chapter 14 29
in. Order as function object ñWrap up method in. Order in an object to pass it as an argument to sort. ñDefine an interface /** * transitive, and anti-symmetric order on Element instances */ public interface Order<Element> { boolean in. Order (Element e 1, Element e 2); } ñ A concrete order will implement this interface for some particular Element. May 2004 NH-Chapter 14 30
Implementing Order interface ñ To sort a list of Student by grade, define a class (Grade. Order) implementing the interface, and then instantiated the class to obtain the required object. //Order Students by decreasing final. Grade class Grade. Order implements Order<Student> { public boolean in. Order (Student s 1, Student s 2) { return s 1. final. Grade() > s 2. final. Grade(); } } May 2004 NH-Chapter 14 31
Anonymous classes ñDefine the class and instantiate it in one expression. ñFor example, new Order<Student>() { boolean in. Order(Student s 1, Student s 2) { return s 1. final. Grade() > s 2. final. Grade(); } } ñ This expression ñ defines an anonymous class implementing interface Order<Student>, and ñ creates an instance of the class. May 2004 NH-Chapter 14 32
Generalizing sort using generic methods ñ Generalized sort methods have both a list and an order as parameters. public class Sorts { public static <Element> void selection. Sort ( List<Element> list, Order<Element> order) {…} public static <Element> void bubble. Sort ( List<Element> list, Order<Element> order) {… } } May 2004 NH-Chapter 14 33
Generalizing sort using generic methods ñ The order also gets passed to auxiliary methods. The selection sort auxiliary method smallest. Of will be defined as follows: private static <Element> int smallest. Of ( List<Element> list, int first, int last, Order<Element> order ) {…} May 2004 NH-Chapter 14 34
Sorting a roll by grade ñIf roll is a List<Student>, to sort it invoke: Sorts. selection. Sort(roll, new Grade. Order()); ñ Or, using anonymous classes: Sorts. selection. Sort(roll, new Order<Student>() { boolean in. Order(Student s 1, Student s 2) { return s 1. final. Grade() > s 2. final. Grade(); } } ); May 2004 NH-Chapter 14 35
Sorts as generic objects ñ wrap sort algorithm and ordering in the same object. ñ Define interface Sorter : //A sorter for a List<Element>. public interface Sorter<Element> { //e 1 precedes e 2 in the sort ordering. public boolean in. Order (Element e 1, Element e 2); //Sort specified List<Element> according to this. in. Order. public void sort (List<Element> list); } May 2004 NH-Chapter 14 36
Sorts as generic objects ñProvide specific sort algorithms in abstract classes, leaving the ordering abstract. public abstract class Selection. Sorter<Element> implements Sorter<Element> // Sort the specified List<Element> using selection sort. public void sort (List<Element> list) { … } } Selection sort algorithm May 2004 NH-Chapter 14 37
Sorts as generic objects ñ To create a concrete Sorter, we extend the abstract class and furnish the order: class Grade. Sorter extends Selection. Sorter<Student> { public boolean in. Order (Student s 1, Student s 2){ return s 1. final. Grade() > s 2. final. Grade(); } } May 2004 NH-Chapter 14 38
Sorts as generic objects ñInstantiate the class to get an object that can sort: Grade. Sorter grade. Sorter = new Grade. Sorter(); grade. Sorter. sort(roll); ñ Using an anonymous class, Selection. Sorter<Student> grade. Sorter = new Selection. Sorter<Student>() { public boolean in. Order (Student s 1, Student s 2){ return s 1. final. Grade() > s 2. final. Grade(); } }; grade. Sorter. sort(roll); May 2004 NH-Chapter 14 39
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 Ordered. List ( does not extend List) public interface Ordered. List<Element> A finite ordered list. May 2004 NH-Chapter 14 40
Ordered Lists ñ Ordered. List 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); ñ Ordered. List invariant: ñ for all indexes i, j: ordering(). in. Order(get(i), get(j)) implies i < j. ñ Ordered. List add method is specified as: public void add (Element element) Add the specified element to the proper place in this Ordered. List. May 2004 NH-Chapter 14 41
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. May 2004 NH-Chapter 14 42
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. May 2004 NH-Chapter 14 43
Generic search method item. Index private <Element> int item. Index (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. in. Order(list. get(i), item) for all indexes i: i >= result implies !order. in. Order(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. May 2004 NH-Chapter 14 44
Implementation of item. Index private <Element> int item. Index (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. in. Order(list. get(i), item) // for all indexes i: i > high implies !order. in. Order(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. in. Order(list. get(mid), item)) low = mid+1; else high = mid-1; } return low; } May 2004 NH-Chapter 14 45
Searching for 42 in low May 2004 item 42 low high mid 0 14 ? ? high ? ? ? ? (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 46
Searching for 42 high low May 2004 item 42 low high mid 8 14 7? s s s s 28 ? ? (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 47
Searching for 42 low high May 2004 item 42 low high mid 8 10 11 s s s s 28 ? ? ? 56 g g g (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 48
Searching for 42 low high May 2004 item 42 low high mid 8 10 10 s s s s 28 s 33 ? 56 g g g (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 49
Searching for 42 high low item 42 low high mid 11 10 10 s s s s 28 s 33 40 56 g g g (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) 42 is not found using item. Index algorithm May 2004 NH-Chapter 14 50
Searching for 12 low May 2004 item 12 low high mid 0 14 ? ? high ? ? ? ? (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 51
Searching for 12 high low May 2004 item 12 low high mid 0 6 7 ? ? 28 g g g g (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 52
Searching for 12 high low May 2004 item 12 low high mid 0 2 3 ? ? ? 12 g g g 28 g g g g (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 53
Searching for 12 low high May 2004 item 12 low high mid 2 2 1 s 5 ? 12 g g g 28 g g g g (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) NH-Chapter 14 54
Searching for 12 high low item 12 low high mid 3 2 2 s 5 ? 12 g g g 28 g g g g (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) 12 found in list at index 3 May 2004 NH-Chapter 14 55
index. Of using binary search /** * Uses binary search to find where and if an element is in a list. * require: item != null * ensure: * if item == no element of list index. Of(item, list) == -1 * else item == list. get(index. Of(item, list)), * and index. Of(item, list) is the smallest value for which this is true */ public <Element> int index. Of (Element item, List<Element> list, Order<Element> order) { int i = item. Index(item, list, order); if (i < list. size() && list. get(i). equals(item)) return i; else return -1; } May 2004 NH-Chapter 14 56
Recall sequential (linear) search public int index. Of (Element element) { int i = 0; // index of the next element to examine while (i < this. size() && !this. get(i). equals(element)) i = i+1; if (i < this. size()) return i; else return -1; } May 2004 NH-Chapter 14 57
Relative algorithm efficiency ñ Number of steps required by the algorithm with a list of length n grows in proportion to ñSelection sort: n 2 ñ Bubble sort: n 2 ñ Linear search: n ñ Binary search: log May 2004 2 n NH-Chapter 14 58
Loop invariant ñ Loop invariant: condition that remains true as we repeatedly execute loop body; it captures the fundamental intent in iteration. ñ Partial correctness: assertion that loop is correct if it terminates. ñ Total correctness: assertion that loop is both partially correct, and terminates. May 2004 NH-Chapter 14 59
Loop invariant ñ loop invariant: ñ it is true at the start of execution of a loop; ñ remains true no matter how many times loop body is executed. May 2004 NH-Chapter 14 60
Correctness of item. Index algorithm 1. private <Element> int item. Index (Element item, List<Element> list, Order<Element> order) { 2. int low = 0; 3. int high = list. size() - 1; 4. while (low <= high) { 5. mid = (low+high)/2; 6. if (order. in. Order(list. get(mid), item)) 7. low = mid+1; 8. else 9. high = mid-1; 10. } 11. return low; 12. } May 2004 NH-Chapter 14 61
Key invariant ñ Purpose of method is to find index of first list element greater than or equal to a specified item. ñ Since method returns value of variable low, we want low to satisfy this condition when the loop terminates for all indexes i: i < low implies order. in. Order(list. get(i), item) for all indexes i: i >= low implies !order. in. Order(list. get(i), item) May 2004 NH-Chapter 14 62
Key invariant ñ This holds true at all four key places (a, b, c, d). ñ It’s vacuously true for indexes less than low or greater than high (a) ñ We assume it holds after merely testing the condition (b) and (d) ñ If condition holds before executing the if statement and list is sorted in ascending order, it will remain true after executing the if statement (condition c). May 2004 NH-Chapter 14 63
Key invariant ñ We are guaranteed that for 0 <= i < mid order. in. Order(list. get(i), item) ñ After the assignment, low equals mid+1 and so for 0 <= i < low order. in. Order( list. get(i), item) ñ This is true before the loop body is done: for high < i < list. size( !order. in. Order( list. get(i), item) May 2004 NH-Chapter 14 64
Partial correctness ñ If loop body is not executed at all, and point (d) is reached with low == 0 and high == -1. ñ If the loop body is performed, at line 6, low <= mid <= high. ñ low <= high becomes false only if ñ mid == high and low is set to mid + 1 or ñ low == mid and high is set to mid - 1 ñ In each case, low == high + 1 when loop is exited. May 2004 NH-Chapter 14 65
Partial correctness ñ The following conditions are satisfied on loop exit: ñ low == high+1 ñ for all indexes i: i < low implies ñ order. in. Order(list. get(i), item) ñ for all indexes i: i > high implies ñ !order. in. Order(list. get(i), item) ñ which imply ñ for all indexes i: i < low implies ñ order. in. Order(list. get(i), item) ñ for all indexes i: i >= low implies ñ !order. in. Order(list. get(i), item) May 2004 NH-Chapter 14 66
Loop termination ñ When the loop is executed, mid will be set to a value between high and low. ñ The if statement will either cause low to increase or high to decrease. ñ This can happen only a finite number of times before low becomes larger than high. May 2004 NH-Chapter 14 67
Summary ñ Sorting and searching are two fundamental list operations. ñ Examined two simple sort algorithms, selection sort and bubble sort. ñ Both of these algorithms make successive passes through the list, getting one element into position on each pass. ñ They are order n 2 algorithms: time required for the algorithm to sort a list grows as the square of the length of the list. ñ We also saw a simple modification to bubble sort that improved its performance on a list that was almost sorted. May 2004 NH-Chapter 14 68
Summary ñ Considered how to generalize sorting algorithms so that they could be used for any type list and for any ordered. ñ We proposed two possible homes for sort algorithms: ñ static generic methods, located in a utility class; ñ abstract classes implementing a Sorter interface. ñ With later approach, we can dynamically create “sorter objects” to be passed to other methods. ñ Introduced Java’s anonymous class construct. ñ in a single expression we can create and instantiate a nameless class that implements an existing interface or extends an existing class. May 2004 NH-Chapter 14 69
Summary ñ Considered Ordered. List container. ñ Developed binary search: search method for sorted lists. ñ At each step of the algorithm, the middle of the remaining elements is compared to the element being searched for. ñ Half the remaining elements are eliminated from consideration. ñ Major advantage of binary search: it looks at only log 2 n elements to find an item on a list of length n. May 2004 NH-Chapter 14 70
Summary ñ Two steps were involved in verifying the correctness of the iteration in evaluating the correctness of binary search algorithm: ñ First, demonstrated partial correctness: iteration is correct if it terminates. ñ found a key loop invariant that captured the essential behavior of the iteration. ñ Second, showed that iteration always terminates. May 2004 NH-Chapter 14 71
Summary ñ A loop invariant is a condition that remains true no matter how many times the loop body is performed. ñ The key invariant insures that when the loop terminates it has satisfied its purpose. ñ Verification of the key invariant provides a demonstration of partial correctness. May 2004 NH-Chapter 14 72
- Slides: 72