1 / 72

# Chapter 14: Sorting and Searching - PowerPoint PPT Presentation

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.

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Chapter 14: Sorting and Searching' - rasha

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

• 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.

• 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.

• 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.

• Example: to order a List<Student> need

• 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.

public boolean inOrder (Student first, Student second)

• 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.

• 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.

• 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.

• A list is ordered:

• s1<s2, thens1 comes before s2 on the list:

• Or

for all indexes i, j: inOrder(list.get(i),list.get(j)) implies i < j.

for all indexes i and j,i<j implies!inOrder(list.get(j),list.get(i)).

• Design:

• Find the smallest element in the list, and put it in as first.

• Find the second smallest and put it as 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.

• While making list.get(0) refer to list.get(2),

• loose reference to original entry referenced by list.get(0).

/**

* Sort the specified List<Student> using selection sort.

* @ensure

* for all indexes i, j:

* inOrder(list.get(i),list.get(j)) implies i < j.

*/

publicvoid 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)

last = list.size() - 1;

first = 0;

while (first < last) {

small = smallestOf(list,first,last);

interchange(list,first,small);

first = first+1;

}

}

/**

* Index of the smallest of

* list.get(first) through list.get(last)

*/

privateint smallestOf (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(next-1)

small = first;

next = first+1;

while (next <= last) {

if (inOrder(list.get(next),list.get(small)))

small = next;

next = next+1;

}

return small;

}

/**

* 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)

*/

privatevoid interchange (List<Student> list,

int i, int j) {

Student temp = list.get(i);

list.set(i, list.get(j));

list.set(j, temp);

}

• 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.

Pass 4

// Sort specified List<Student> using bubble sort.

publicvoid sort (List<Student> list) {

int last; // index of last element to position on this pass

last = list.size() - 1;

while (last > 0) {

makePassTo(list, last);

last = last-1;

}

}

// Make a pass through the list, bubbling an element to position last.

privatevoid 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;

}

}

• 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.

• Sorting algorithms are independent of:

• the method inOrder, as long as it satisfies ordering requirements.

• The elements in the list being sorted.

• Want to generalize the sort to List<Element> instances with the following specification:

• Thus:

• Need to learn about generic methods.

• Need to make the inOrder method part of a class.

public <Element> void selectionSort ( List<Element> list, Order<Element> order)

• 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.

• In the method definition:

Method type parameter

• swap is now a generic method: it can swap to list entries of any given type.

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);

}

• 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.

• 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.

• Wrap up method inOrder in an object to pass it as an argument to sort.

• Define an interface

• A concrete order will implement this interface for some particular Element.

/**

* transitive, and anti-symmetric order on Element instances

*/

publicinterface Order<Element> {

boolean inOrder (Element e1, Element e2);

}

• 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.

publicboolean inOrder (Student s1, Student s2) {

}

}

• Define the class and instantiate it in one expression.

• For example,

• This expression

• defines an anonymous class implementing interface Order<Student>, and

• creates an instance of the class.

new Order<Student>() {

boolean inOrder(Student s1, Student s2) {

}

}

• Generalized sort methods have both a list and an order as parameters.

publicclass Sorts {

publicstatic <Element> void selectionSort (

List<Element> list, Order<Element> order) {…}

publicstatic <Element> void bubbleSort (

List<Element> list, Order<Element> order) {… }

}

• The order also gets passed to auxiliary methods. The selection sort auxiliary method smallestOf will be defined as follows:

privatestatic <Element> int smallestOf (

List<Element> list, int first, int last,

Order<Element> order ) {…}

• If roll is a List<Student>, to sort it invoke:

• Or, using anonymous classes:

Sorts.selectionSort(roll,

new Order<Student>() {

boolean inOrder(Student s1, Student s2) {

}

}

);

• wrap sort algorithm and ordering in the same object.

• Define interface Sorter :

//A sorter for a List<Element>.

publicinterface Sorter<Element> {

//e1 precedes e2 in the sort ordering.

publicboolean inOrder (Element e1, Element e2);

//Sort specified List<Element> according to this.inOrder.

publicvoid sort (List<Element> list);

}

• Provide specific sort algorithms in abstract classes, leaving the ordering abstract.

public abstract class SelectionSorter<Element> implements Sorter<Element> {

// Sort the specified List<Element> using selection sort.

public void sort (List<Element> list) { … }

}

Selection sort algorithm

• To create a concrete Sorter, we extend the abstract class and furnish the order:

publicboolean inOrder (Student s1, Student s2){

}

}

• Instantiate the class to get an object that can sort:

• Using an anonymous class,

new SelectionSorter<Student>() {

publicboolean inOrder (Student s1, Student s2){

}

};

• 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.

• 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:

Add the specified element to the proper place in this OrderedList.

• 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.

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.

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.

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 !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.

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;

}

return low;

}

high

item

42

low

0

high

14

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

mid

?

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

Searching for 42 in

42

low

8

high

14

s

s

s

s

s

s

s

28

?

?

?

?

?

?

?

mid

7?

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

low

Searching for 42

high

42

low

8

high

10

s

s

s

s

s

s

s

28

?

?

?

56

g

g

g

high

mid

11

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

low

Searching for 42

42

low

8

high

10

s

s

s

s

s

s

s

28

s

33

?

56

g

g

g

high

mid

10

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

Searching for 42

low

42

low

11

high

10

s

s

s

s

s

s

s

28

s

33

40

56

g

g

g

high

mid

10

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

Searching for 42

low

high

item

12

low

0

high

14

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

mid

?

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

Searching for 12

12

low

0

high

6

?

?

?

?

?

?

?

28

g

g

g

g

g

g

g

mid

7

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

low

Searching for 12

high

12

low

0

high

2

?

?

?

12

g

g

g

28

g

g

g

g

g

g

g

mid

3

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

low

Searching for 12

high

12

low

2

high

2

s

5

?

12

g

g

g

28

g

g

g

g

g

g

g

mid

1

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

Searching for 12

low

high

12

low

3

high

2

s

5

?

12

g

g

g

28

g

g

g

g

g

g

g

mid

2

(0)

(1)

(2)

(3)

(4)

(5)

(6)

(7)

(8)

(9)

(10)

(11)

(12)

(13)

(14)

Searching for 12

high

low

12 found in list at index 3

/**

* 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;

}

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;

}

• 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

• 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.

• loop invariant:

• it is true at the start of execution of a loop;

• remains true no matter how many times loop body is executed.

• private <Element> int itemIndex (Element item, List<Element> list, Order<Element> order) {

• int low = 0;

• int 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;

• }

• return low;

• }

• 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)

• 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).

• 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)

• If loop body is not executed at all, and point (d) is reached withlow == 0andhigh == -1.

• If the loop body is performed, at line 6, low <= mid <= high.

• low <= highbecomes false only if

• mid == highandlowis set tomid + 1or

• low == midandhighis set tomid - 1

• In each case,low == high + 1when loop is exited.

• 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

• !order.inOrder(list.get(i),item)

• When the loop is executed, midwill be set to a value between highand 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 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.

• 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.

• 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.

• 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.

• 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.