| Sorting and searching |
| Two fundamental list operations. | ||
| Sorting | ||
| Searching | ||
| Sorted lists. | ||
| Selection/bubble sort. | ||
| Binary search. | ||
| Loop invariant. | ||
| There must be a way of comparing objects to determine which should come first. There must be an ordering relation. | |
| There must be an operator to compare the objects to put them in order. | |
| The ordering is antisymmetric. (a < b -> b !<a) | |
| The ordering is transitive. (a<b,b<c -> a<c) | |
| The ordering is total with respect to some “equivalence” on the class. (a<b or a>b or a==b, but only one; here “==“ means “equivalent with respect to the ordering”) |
| public boolean lessThan (Student s) | |
| s1.lessThan(s2) | |
| Returns true if s1<s2 and false if s1>=s2. | |
| for i > 0, j < size(), | |
| get(i).lessThan(get(j)) implies i < j. |
| Find the smallest element in the list, and put it in first. | |
| Find the second smallest and put it second, etc. |
| Find the smallest. | |
| Interchange it with the first. | |
| Find the next smallest. | |
| Interchange it with the second. | |
| Find the next smallest. | |
| Interchange it with the third. | |
| Find the next smallest. | |
| Interchange it with the fourth. |
| To interchange items, we must store one of the variables temporarily. |
| 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). | |
| 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. |
| This algorithm represents essentially the same number of steps as the selection sort. | |
| If make a pass through the list without interchanging, then the list is ordered. This makes the algorithm fast if it is mostly ordered. |
| 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. |
| private int itemIndex (Student item, | |
| StudentList list) | |
| The proper place for the specified item on the specified list, found using binary search. | |
| require: | |
| list is sorted in increasing order | |
| ensure: | |
| 0 <= result <= list.size() | |
| for 0 <= i < result | |
| list.get(i) < item | |
| for result <= i < list.size() | |
| list.get(i) >= item |
| private int itemIndex (Student item, | |
| StudentList list) { | |
| int low; //lowest index considered | |
| int high; //highest index considered | |
| int mid; //middle between high and low | |
| low =0 | |
| high = list.size() -1; | |
| while (low <= high) { | |
| mid = (low+high)/2; | |
| if (list.get(mid).lessThan(item)) | |
| low = mid+1; | |
| else | |
| high = mid-1; | |
| } | |
| return low; | |
| } |
| /** | |
| * Uses binary search to find where and if an element | |
| * is in a list. | |
| * require: | |
| * item != null | |
| * ensure: | |
| * if item == no element of list | |
| * indexOf(item, list) == -1 | |
| * else | |
| * item == list.get(indexOf(item, list)), | |
| * and indexOf(item, list) is the smallest | |
| * value for which this is true | |
| */ | |
| public int indexOf(Student item, | |
| StudentList list){ | |
| int i = itemIndex(item, list); | |
| if (i<list.size() && | |
| list.get(i).equals(item)) | |
| return i; | |
| else | |
| return -1; | |
| } |
| public int indexOf (Student obj) { | |
| int i; | |
| int length; | |
| length = this.size(); | |
| i = 0; | |
| while (i < length && !obj.equals(get(i))) | |
| i = i+1; | |
| if ( i < length) | |
| return i; | |
| else | |
| return -1;// item not found | |
| } | |
| A loop invariant is a condition that remains true as we repeatedly execute the loop body, and captures the fundamental intent in iteration. | |
| partial correctness: the assertion that a loop is correct if it terminates. | |
| total correctness: the assertion that a loop is both partially correct, and terminates. | |
| loop invariant: a condition that is true at the start of execution of a loop and remains true no matter how many times the body of the loop is performed. |
| 1.private int itemIndex (Student item, | |
| StudentList list) { | |
| 2. low =0 | |
| 3. high = list.size() -1; | |
| 4. while (low <= high) { | |
| 5. mid = (low+high)/2; | |
| 6. if (list.get(mid).lessThan(item)) | |
| 7. low = mid+1; | |
| 8. else | |
| 9. high = mid-1; | |
| 10.} | |
| 11. return low; | |
| 12.} | |
| At line 6, we can conclude | |
| 0 <= low <= mid <= high < list.size() |
| for 0 <= i < low | ||
| list.get(i) < item | ||
| for high < i < list.size() | ||
| list.get(i) >= item | ||
| This holds true at all four key places (a, b, c, d). | ||
| It is 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 the condition holds before executing the if statement and the list is sorted in ascending order, it will remain true after executing the if statement (condition c). | ||
| We are guaranteed that | |
| for 0 <= i < mid | |
| list.get(i) < item | |
| After the assignment, low equals mid+1 and so | |
| for 0 <= i < low | |
| list.get(i) < item | |
| This is true before the loop body is done: | |
| for high < i < list.size( | |
| list.get(i) >= item |
| If the 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 the loop is exited. | ||
| The following conditions are satisfied on loop exit | |
| low == high + 1 | |
| for 0 <= i <= low | |
| list.get(i) < item | |
| for high < i < list.size() | |
| list.get(i) >= item | |
| which implies | |
| for 0 <= i < low | |
| list.get(i) < item | |
| for low <= i < list.size() | |
| list.get(i) >= item | |
| 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. |
| Sorting | ||
| selection sort | ||
| bubble sort | ||
| Searching | ||
| Sequential/linear search | ||
| binary search | ||
| Verifying correctness of iterations | ||
| partial correctness | ||
| loop invariant | ||
| key invariant | ||
| termination | ||