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