








Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Community
Ask the community for help and clear up your study doubts
Discover the best universities in your country according to Docsity users
Free resources
Download our free guides on studying techniques, anxiety management strategies, and thesis advice from Docsity tutors
This document examines elementary searching and sorting algorithms, such as bubble sort and selection sort, in the context of applying the vector Abstract Data Type (ADT) and introducing asymptotic algorithm analysis. The document also discusses growth rates, big-Omicron expressions, and the impact of input size on algorithm performance.
Typology: Exams
1 / 14
This page cannot be seen from the preview
Don't miss anything!
Searching and sorting are two of the most frequently performed computing tasks. In this chapter we will examine several elementary searching and sorting algorithms in the interests of applying the vector ADT and of in- troducing asymptotic algorithm analysis. We will briefly revisit sorting in Chapter 6, and we will take another more intensive look at sorting in Chapter 9, after having developed the tools to understand and implement the more sophisticated and better-performing algorithms presented there.
Our current class diagram appears below in Figure 5.1. In this chapter we add classes Search and Sort, both of which depend on class Vector.
Fig. 5.1. Our current model; a Set has-a DynamicVector, and classes Search and Sort depend on class Vector
38 Chapter 5 An Introduction to Vector Searching and Sorting
The goal of asymptotic algorithm analysis is to arrive at an expression for the growth rate of an algorithm's running time or space requirement in terms of the algorithm's input size. Such expressions allow us to compare the performance of two algorithms independent of any particular comput- ing hardware. In other words, asymptotic algorithm analysis helps us to choose among two or more algorithms designed to solve the same problem without having to implement the algorithms and compare their perform- ance by executing them on a particular computer. Asymptotic algorithm analysis facilitates the formal comparison of algorithms, making empirical comparisons unnecessary.
5.2.1 Growth Rates
The key concept in asymptotic algorithm analysis is that of a growth rate.
growth rate : a mathematical expression that tells us how rapidly an algo- rithm's running time or space requirement increases as the problem size in- creases
Graphs of some of the growth rates most commonly encountered in the computer science literature appear below in Figure 5.2. The input size or problem size is denoted n. The base-2 logarithm function is denoted lg.
Fig. 5.2. Algorithmic Growth Rates Commonly Encountered in the Computer Sci- ence Literature
40 Chapter 5 An Introduction to Vector Searching and Sorting
The comparison of the items at indices 4 and 3 is followed by another swap, and the subsequent comparison of the items at indices 3 and 2 re- sults in yet another swap, yielding the array shown below.
Because the items at indices 2 and 1 are in ascending order no swap oc- curs. But the -2 and the 7 are out of order and must be swapped. We are left with the following array.
This concludes the algorithm's first pass. The next pass begins in the same fashion but need not traverse the entire array, for the -2 has reached its final resting place. After the second pass the 0 has reached its final rest- ing place and the array is in the state shown below.
Because the -2 and the 0 have reached their final destinations the algo- rithm's third pass must examine only locations 2 through 8. After the third pass the 3 has been placed at index 2 and the array is in the state shown be- low.
Subsequent passes proceed in the same fashion. On its final pass the al- gorithm deals only with the items at indices 7 and 8. The result is of course a sorted array.
5.2 Asymptotic Algorithm Analysis 41
In analyzing the algorithm, we consider three cases: best, average, and worst; and we count the number of comparisons and the number of swaps because comparing and swapping are the algorithm's two fundamental op- erations.
Counting Comparisons
Observe that for an input size of n the bubble sort algorithm performs n - 1 passes. The algorithm does n - 1 comparisons on the first pass, n - 2 comparisons on the second pass, n - 3 comparisons on the third pass, ... , two comparisons on the next-to-last pass, and one comparison on the final pass. Thus the number of comparisons required when the input size is n is equal to
. 2
( 1 ) ( 1 ) ( 2 ) ( 3 ) ... 3 2 1 21 n^221 n nn n n n = โ โ โ + โ + โ + + + + =
This is true in the best, average, and worst cases.
Counting Swaps
In the best case, i.e., when the data are already sorted, the bubble sort algo- rithm does no swapping. In the worst case, i.e., when the data are sorted in descending order, the algorithm must swap each time it compares. Thus
the number of swaps in the worst case is 21 n^2 โ 21 n.
We may safely assume that the algorithm must swap after every other comparison, or about half the time, on average. Thus the number of swaps
in the average case is 14 n^2 โ 41 n.
Summing our results, we arrive at the following.
Table 5.1. Best-, average-, and worst-case running times for the bubble sort algo- rithm
Case Comparisons Swaps Total Operations
Best 21 n^2 โ 21 n 0 21 n^2 โ 21 n
Average 21 n^^2 โ^21 n 41 n^^2 โ^41 n 43 n^^2 โ 43 n
Worst 21 n^^2 โ^21 n 21 n^^2 โ^21 n n^2 โ n
5.2 Asymptotic Algorithm Analysis 43
Because the smallest value is now in its final resting place, the algo- rithm need not examine location 0 on its second pass. The algorithm scans locations 1 through 8 and finds the smallest value among those locations,
On its third pass the selection sort need not examine locations 0 and 1. Locations 2 through 8 are scanned and 3 is found to be the smallest value among those locations. The 3 is swapped with the value at index 2. The re- sulting array appears below.
On its fourth pass the algorithm swaps the 4 with the value at index 3, arriving at the following array.
This process continues until the array is sorted.
Time Analysis of the Selection Sort
We again count comparisons and swaps for the best, average, and worst cases. The number of comparisons performed in each case is the same as
for the bubble sort algorithm, 21 n^2 โ 21 n. In the best case, i.e., when the
data are already in ascending order, the selection sort algorithm never swaps. In the worst case, i.e., when the data are in descending order, the algorithm must swap once on each pass, or n - 1 times. In the average case
the algorithm must swap half as often, or 21 n โ 21 times. Summing our re-
sults for each case, we arrive at the following.
44 Chapter 5 An Introduction to Vector Searching and Sorting
Table 5.2. Best-, average-, and worst-case running times for the selection sort al- gorithm
Case Comparisons Swaps Total Operations
Best 21 n^2 โ 21 n 0 21 n^2 โ 21 n
Average 21 n^2 โ 21 n 21 n โ 21 21 n^2 โ 21
Worst 21 n^2 โ 21 n n - 1 21 n^2 + 21 n โ 1
We discard the constant and linear terms and coefficients and are left with n^2 for each of the three cases. Thus the selection sort algorithm is in O( n^2 ) in the best, average, and worst cases.
We will now examine two searching algorithms, the linear search and the binary search.
5.3.1 The Linear Search Algorithm
The linear search algorithm amounts to scanning the elements of a linear collection, in our case a vector, until a target element is found or is deter- mined to be absent from the collection. If the target element is the first element, then only one comparison is required. In the average case about one-half of the elements must be examined before the target element is
found, i.e., 21 n comparisons must be performed in the average case.
The linear search algorithm's worst-case performance occurs when the target element is not a member of the collection. The number of compari- sons required in this case depends on whether the collection is sorted. If the collection is not sorted, then all n elements must be examined in order to determine that the target is absent. If the collection is sorted, then about half of the elements must be examined, on average, to determine that the target is absent. These results are summarized in the table below.
46 Chapter 5 An Introduction to Vector Searching and Sorting
Because 65 > 23 and the collection is sorted, if the target element is pre- sent it must occupy one of locations 9 through 11, and so the subcollection at indices 6 through 8 may be discarded.
The middle element of this subcollection is at index (11 + 9) / 2 = 10. The element at index 10 is the target element, and so the search is com- plete. If the target element had been absent, then the algorithm would have terminated after having "homed in" on a one-element subcollection. The binary search algorithm is an example of a divide-and-conquer al- gorithm.
divide-and-conquer algorithm : an algorithm that solves a problem by re- peatedly reducing the problem size
Java implementations of the bubble sort, selection sort, linear search, and binary search are shown below. The implementations assume that any in- stance of Vector to which an algorithm is being applied contains ele- ments that can be ordered. Instances of any class that implements Java's Comparable interface satisfy this condition.
5.4.1 Java Interfaces and Interface Comparable
The Java programming language provides a facility for creating ADT specifications, the interface. The term interface is both a UML term and a Java term. In either context the term refers to an ADT. A UML interface is represented in the manner of Cloneable from Figure 1.6. A Java inter- face is written in the Java programming language. The code for Java inter- face Comparable appears below.
public interface Comparable { int compareTo(Object o); }
5.4 Implementing the Aforementioned Algorithms: Classes Search and Sort 47
Observe that interface Comparable contains no implementation. This is in keeping with the fact that interfaces are for specifying ADTs. Recall that an ADT does not specify implementation details; an ADT specifies only what a data type can do, not how it is to be done. A data structure provides the how. What, then, is the purpose of a Java interface? A Java interface may be thought of as a sort of contract. Any instantiable Java class that realizes an interface must implement each of the interface's methods. A Java class that fails to do so will not compile. Any class that implements interface Comparable offers a public method called compareTo. This method compares the calling object, this, with object o. If this is less than o, then compareTo returns a negative value. If this is equal to o, then compareTo returns 0. If this is greater than o, then compareTo returns a positive value. Thus instances of any class that implements Comparable can be ordered.
5.4.2 Classes Search and Sort
The linear and binary search algorithms are implemented as class methods of class Search, and the bubble and selection sort algorithms are imple- mented as class methods of class Sort. Each method takes an argument of type Vector. Recall that Vector is an abstract class with concrete sub- classes FixedVector and DynamicVector. Because FixedVector is ako Vector and DynamicVector is ako Vector, the actual type of the container passed to any of the methods may be either FixedVector or DynamicVector. In other words, the inheritance implemented in Chapter 4 makes FixedVectors and DynamicVectors interchange- able as far as classes Search and Sort are concerned.
Exercises 49
public static void selectionSort(Vector vec) { int i, j, n = vec.size(), smallPos; Comparable smallest, current; for (i = 0; i < n - 1; i++) { smallPos = i; smallest = (Comparable)vec.elementAt(smallPos); for (j = i + 1; j < n; j++) { current = (Comparable)vec.elementAt(j); if (current.compareTo(smallest) < 0) { smallPos = j; smallest = (Comparable)vec.elementAt(smallPos); } } if (smallPos != i) swap(vec, i, smallPos); } } }