Chapter 14: Sorting and Searching

Download Report

Transcript Chapter 14: Sorting and Searching

An Introduction to
Programming and Object
Oriented Design using Java
2nd 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 inOrder 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 inOrder (Student first, Student second)
 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.
May 2004
NH-Chapter 14
5
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.
May 2004
NH-Chapter 14
6
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.
May 2004
NH-Chapter 14
7
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.
May 2004
NH-Chapter 14
8
Ordered list
A list is ordered:
s1 < s2, then s1 comes before s2 on the list:
for all indexes i, j:
inOrder(list.get(i),list.get(j)) implies i < j.
 Or
for all indexes i and j, i < j implies
!inOrder(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:
*
inOrder(list.get(i),list.get(j)) implies i < j.
*/
public void sort (List<Student> list) {
int first;
// index of first element to con
int last;
// index of last element to cons
int small;
// index of smallest of list.get
last = list.size() - 1;
first = 0;
while (first < last) {
small = smallestOf(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 smallestOf (List<Student> list,
int first,
i
int next;
// index of next element to exami
int small;
// index of the smallest of get(f
small = first;
next = first+1;
while (next <= last) {
if (inOrder(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.si
*
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 = (n2-n)/2
 As n increases, the time to sort the list goes up by this factor
(order n2).
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 positi
last = list.size() - 1;
while (last > 0) {
makePassTo(list, last);
last = last-1;
}
}
// Make a pass through the list, bubbling an element to posit
private void 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;
}
}
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 inOrder, 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 selectionSort (
List<Element> list, Order<Element> order)
 Thus:
 Need to learn about generic methods.
 Need to make the inOrder 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
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
inOrder as function object
Wrap up method inOrder in an object to pass it as
an
argument to sort.
Define
/** an interface
* transitive, and anti-symmetric order on Element i
*/
public interface Order<Element> {
boolean inOrder (Element e1, Element e2);
}
 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
(GradeOrder) implementing the interface, and then
instantiated the class to obtain the required object.
//Order Students by decreasing finalGrade
class GradeOrder implements Order<Student> {
public boolean inOrder (Student s1, Student s2)
return s1.finalGrade() > s2.finalGrade();
}
}
May 2004
NH-Chapter 14
31
Anonymous classes
Define the class and instantiate it in one expression.
For example,
new Order<Student>() {
boolean inOrder(Student s1, Student s2) {
return s1.finalGrade() > s2.finalGrade();
}
}
 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 selectionSort (
List<Element> list, Order<Element> order)
public static <Element> void bubbleSort (
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 smallestOf will be defined as
follows:
private static <Element> int smallestOf (
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.selectionSort(roll, new GradeOrder());
 Or, using anonymous classes:
Sorts.selectionSort(roll,
new Order<Student>() {
boolean inOrder(Student s1, Student s2)
return s1.finalGrade() > s2.finalG
}
}
);
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> {
//e1 precedes e2 in the sort ordering.
public boolean inOrder (Element e1, Element e2);
//Sort specified List<Element> according to thi
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 SelectionSorter<Element> implements So
// Sort the specified List<Element> using selection
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 GradeSorter extends SelectionSorter<Student
public boolean inOrder (Student s1, Student
return s1.finalGrade() > s2.finalGrad
}
}
May 2004
NH-Chapter 14
38
Sorts as generic objects
Instantiate the class to get an object that can sort:
GradeSorter gradeSorter = new GradeSorter();
gradeSorter.sort(roll);
 Using an anonymous class,
SelectionSorter<Student> gradeSorter =
new SelectionSorter<Student>() {
public boolean inOrder (Student s1, Student
return s1.finalGrade() > s2.finalGrad
}
};
gradeSorter.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 OrderedList ( does not extend List)
public interface OrderedList<Element>
A finite ordered list.
May 2004
NH-Chapter 14
40
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:
public void add (Element element)
Add the specified element to the proper place in this OrderedList.
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 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.
 It
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
returns
an index such that
!order.inOrder(list.get(i),item)
 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.
NH-Chapter 14
May 2004
44
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;
}
NH-Chapter 14
May 2004
return low;
}
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
low
May 2004
item
42
low
high
mid
8
14
7?
s
s
s
s
s
s
s
28
?
high
?
?
?
?
?
?
(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
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
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
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 itemIndex 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
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
low
May 2004
item
12
low
high
mid
0
2
3
?
high
?
?
12
g
g
g
28
g
g
g
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
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
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
indexOf 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 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 <Element> int indexOf (Element item,
List<Element> list, Order<Element> order) {
int i = itemIndex(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 indexOf (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: n2
Bubble sort:
Linear search:
Binary search:
May 2004
n2
n
log n
2
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 itemIndex algorithm
1. private <Element> int itemIndex (Element item,
List<Element> list, Order<Element> o
2.
int low = 0;
3.
int high = list.size() - 1;
4.
while (low <= high) {
5.
mid = (low+high)/2;
6.
if (order.inOrder(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.inOrder(list.get(i),item)
for all indexes i: i >= low implies
!order.inOrder(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.inOrder(list.get(i), item)
 After the assignment, low equals mid+1 and so
for 0 <= i < low
order.inOrder( list.get(i), item)
 This is true before the loop body is done:
for high < i < list.size(
!order.inOrder( 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.inOrder(list.get(i),item)
 for all indexes i: i > high implies

!order.inOrder(list.get(i),item)
 which imply
 for all indexes i: i < low implies

order.inOrder(list.get(i),item)
 for all indexes i: i >= low implies

May 2004
!order.inOrder(list.get(i),item)
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 n2 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 OrderedList 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
log2n 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