Title: Chapter 14: Sorting and Searching
1Chapter 14 Sorting and Searching
2Objectives
- 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.
3Objectives
- 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.
4Ordering lists
- To order a list, there must be an order on the
element class. - Well assume
- There is a boolean method inOrder defined for the
class whose instances we want to order.
5Ordering lists
- Example to order a ListltStudentgt 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.
6Ordering lists
- Ordering alphabetically by name, inOrder(s1,s2)
is true if s1s name preceded s2s name
lexicographically. - Ordering by decreasing grade, inOrder(s1,s2) is
true if s1s grade was greater than s2s.
7Order properties
- We write
- s1 lt s2 when inOrder(s1,s2) true
- s1 gt s2 when inOrder(s1,s2) false
- An ordering is antisymmetric it cannot be the
case that both s1 lt s2 and s2 lt s1. - An ordering is transitive. That is, if s1 lt s2
and s2 lt s3 for objects s1, s2, and s3, then s1 lt
s3.
8Order 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.
9Ordered list
- A list is ordered
- s1 lt s2, then s1 comes before s2 on the list
for all indexes i, j inOrder(list.get(i),list.
get(j)) implies i lt j.
for all indexes i and j, i lt j implies!inOrder(li
st.get(j),list.get(i)).
10Selection 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.
11Selection Sort (cont.)
- Find the smallest.
- Interchange it with the first.
- Find the next smallest.
- Interchange it with the second.
12Selection Sort (cont.)
- Find the next smallest.
- Interchange it with the third.
- Find the next smallest.
- Interchange it with the fourth.
13Selection 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).
14Selection sort algorithm
/ Sort the specified ListltStudentgt using
selection sort. _at_ensure for all indexes
i, j inOrder(list.get(i),list.get(j)) implies
i lt j. / public void sort (ListltStudentgt 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 lt
last) small smallestOf(list,first,last) i
nterchange(list,first,small) first
first1
15Selection sort algorithm
/ Index of the smallest of
list.get(first) through list.get(last) / private
int smallestOf (ListltStudentgt 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
first1 while (next lt last) if
(inOrder(list.get(next),list.get(small))) small
next next next1 return small
16Selection sort algorithm
/ Interchange list.get(i) and list.get(j)
require
0 lt i lt list.size() 0 lt j lt list.size()
ensure list.old.get(i)
list.get(j) list.old.get(j)
list.get(i) / private void interchange
(ListltStudentgt list, int i, int j) Student
temp list.get(i) list.set(i,
list.get(j)) list.set(j, temp)
17Analysis 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
time2, n-2 times timen-2, 1 times. - (n-1)x(n-first) (n-1)(n-2)21 (n2-n)/2
- As n increases, the time to sort the list goes up
by this factor (order n2).
18Bubble 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.
19Pass 1
20Pass 2
21Pass 3
Pass 4
22Bubble sort algorithm
// Sort specified ListltStudentgt using bubble
sort. public void sort (ListltStudentgt list)
int last // index of last element to
position on this pass last list.size() -
1 while (last gt 0) makePassTo(list,
last) last last-1 // Make a pass
through the list, bubbling an element to position
last. private void makePassTo (ListltStudentgt
list, int last) int next // index of
next pair to examine. next 0 while (next lt
last) if (inOrder(list.get(next1),list.get
(next))) interchange(list, next,
next1) next next1
23Fine-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.
24Generalizing 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.
25Generalizing the sort methods
- Want to generalize the sort to ListltElementgt
instances with the following specification
public ltElementgt void selectionSort
( ListltElementgt list, OrderltElementgt order)
- Thus
- Need to learn about generic methods.
- Need to make the inOrder method part of a class.
26Generic 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.
27Generic methods
Method type parameter
public ltElementgt void swap (ListltElementgt 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.
28Generic 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.
29Generic swap
- For example, if roll is a ListltStudentgt,
- ListltStudentgt 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.
30inOrder 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 instances / public interface
OrderltElementgt boolean inOrder (Element e1,
Element e2)
- A concrete order will implement this interface
for some particular Element.
31Implementing 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 OrderltStudentgt public
boolean inOrder (Student s1, Student s2)
return s1.finalGrade() gt s2.finalGrade()
32Anonymous classes
- Define the class and instantiate it in one
expression. - For example,
new OrderltStudentgt() boolean inOrder(Student
s1, Student s2) return s1.finalGrade() gt
s2.finalGrade()
- This expression
- defines an anonymous class implementing interface
OrderltStudentgt, and - creates an instance of the class.
33Generalizing sort using generic methods
- Generalized sort methods have both a list and an
order as parameters.
public class Sorts public static ltElementgt
void selectionSort ( ListltElementgt list,
OrderltElementgt order) public static
ltElementgt void bubbleSort ( ListltElementgt list,
OrderltElementgt order)
34Generalizing 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 ltElementgt int smallestOf
( ListltElementgt list, int first, int
last, OrderltElementgt order )
35Sorting a roll by grade
- If roll is a ListltStudentgt, to sort it invoke
Sorts.selectionSort(roll, new GradeOrder())
- Or, using anonymous classes
Sorts.selectionSort(roll, new
OrderltStudentgt() boolean inOrder(Student s1,
Student s2) return s1.finalGrade() gt
s2.finalGrade() )
36Sorts as generic objects
- wrap sort algorithm and ordering in the same
object. - Define interface Sorter
//A sorter for a ListltElementgt. public interface
SorterltElementgt //e1 precedes e2 in the sort
ordering. public boolean inOrder (Element e1,
Element e2) //Sort specified ListltElementgt
according to this.inOrder. public void sort
(ListltElementgt list)
37Sorts as generic objects
- Provide specific sort algorithms in abstract
classes, leaving the ordering abstract.
public abstract class SelectionSorterltElementgt
implements SorterltElementgt // Sort the
specified ListltElementgt using selection
sort. public void sort (ListltElementgt list)
Selection sort algorithm
38Sorts as generic objects
- To create a concrete Sorter, we extend the
abstract class and furnish the order
class GradeSorter extends SelectionSorterltStudentgt
public boolean inOrder (Student s1, Student
s2) return s1.finalGrade() gt
s2.finalGrade()
39Sorts as generic objects
- Instantiate the class to get an object that can
sort
GradeSorter gradeSorter new GradeSorter() grade
Sorter.sort(roll)
- Using an anonymous class,
SelectionSorterltStudentgt gradeSorter new
SelectionSorterltStudentgt() public boolean
inOrder (Student s1, Student s2) return
s1.finalGrade() gt s2.finalGrade() gradeSo
rter.sort(roll)
40Ordered 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 OrderedListltElementgt
- A finite ordered list.
41Ordered 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( ListltElementgt element, int i,
int j) - OrderedList invariant
- for all indexes i, jordering().inOrder(get(i),get
(j)) implies i lt j. - OrderedList add method is specified as
- public void add (Element element)
- Add the specified element to the proper place in
this OrderedList.
42Binary 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.
43Binary Search for 42
list.get(7) lt 42 No need to look below 8
list.get(11) gt 42 No need to look above 10
list.get(9)lt42 No need to look below 10
Down to one element, at position 10 this isnt
what were looking for, so we can conclude that
42 is not in the list.
44Generic search method itemIndex
private ltElementgt int itemIndex (Element item,
ListltElementgt list, OrderltElementgt
order) Proper place for item on list found using
binary search. require list is sorted according
to order. ensure 0 lt result result lt
list.size() for all indexes i i lt result
implies order.inOrder(list.get(i),item) for
all indexes i i gt 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.
45Implementation of itemIndex
private ltElementgt int itemIndex (Element item,
ListltElementgt list, OrderltElementgt order) int
low // the lowest index being examined int
high // the highest index begin examined
// for all indexes i i lt low implies
order.inOrder(list.get(i),item) // for all
indexes i i gt high implies !order.inOrder(list.ge
t(i),item) int mid // the middle item
between low and high. mid (lowhigh)/2 low
0 high list.size() - 1 while (low lt high)
mid (lowhigh)/2 if (order.inOrder(list.g
et(mid),item)) low mid1 else high
mid-1 return low
46Searching for 42 in
47Searching for 42
high
48Searching for 42
49Searching for 42
low
50Searching for 42
low
42 is not found using itemIndex algorithm
51Searching for 12
52Searching for 12
high
53Searching for 12
high
54Searching for 12
low
high
55Searching for 12
low
high
12 found in list at index 3
56indexOf 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 ltElementgt int indexOf (Element item,
ListltElementgt list, OrderltElementgt order) - int i itemIndex(item, list, order)
- if (i lt list.size() list.get(i).equals(item))
- return i
- else
- return -1
57Recall sequential (linear) search
- public int indexOf (Element element)
- int i 0 // index of the next element to
examine - while (i lt this.size() !this.get(i).equals(el
ement)) - i i1
- if (i lt this.size())
- return i
- else
- return -1
58Relative algorithm efficiency
- Number of steps required by the algorithm with a
list of length n grows in proportion to - Selection sort n2
- Bubble sort n2
- Linear search n
- Binary search log2n
59Loop 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.
60Loop 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.
61Correctness of itemIndex algorithm
- private ltElementgt int itemIndex (Element
item, ListltElementgt list, OrderltElementgt
order) - int low 0
- int high list.size() - 1
- while (low lt high)
- mid (lowhigh)/2
- if (order.inOrder(list.get(mid),item))
- low mid1
- else
- high mid-1
-
- return low
-
62Key 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 lt low implies order.inOrder(
list.get(i),item) for all indexes i i gt low
implies !order.inOrder(list.get(i),item)
63Key invariant
- This holds true at all four key places (a, b, c,
d). - Its 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).
64Key invariant
- We are guaranteed that
- for 0 lt i lt mid
- order.inOrder(list.get(i), item)
- After the assignment, low equals mid1 and so
- for 0 lt i lt low
- order.inOrder( list.get(i), item)
- This is true before the loop body is done
- for high lt i lt list.size(
- !order.inOrder( list.get(i), item)
65Partial 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 lt
mid lt high. - low lt 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.
66Partial correctness
- The following conditions are satisfied on loop
exit - low high1
- for all indexes i i lt low implies
- order.inOrder(list.get(i),item)
- for all indexes i i gt high implies
- !order.inOrder(list.get(i),item)
- which imply
- for all indexes i i lt low implies
- order.inOrder(list.get(i),item)
- for all indexes i i gt low implies
- !order.inOrder(list.get(i),item)
67Loop 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.
68Summary
- 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.
69Summary
- 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 Javas 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.
70Summary
- 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.
71Summary
- 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.
72Summary
- 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.