Section 2.5: Analysis of Algorithms

Abstract:

By analysis of algorithms we mean the study of the efficiency of the algorithms. In this section we will measure the efficiency of an algorithm by counting operations (and of course we are shooting for a small number!).

Counting operations directly

In algorithm SequentialSearch (p. 146/148), we search for element x in a list of n items. SequentialSearch is a direct method, by comparison with algorithm BinarySearch (p. 130), which is recursive. Is one algorithm more efficient than the other?

In the SequentialSearch, there are three rather interesting cases:

We will consider the worst-case scenario as the benchmark.

Counting Using Recurrence Relations

Algorithm BinarySearch is recursive: it calls itself. Starting from a list of length n it makes one comparison and then calls itself with a list of half its initial length. Hence the number of comparisons for the list of length n, C(n), would be

displaymath174

and C(1)=1. Use the ``expand, guess, and verify'' approach: in the worst-case scenario, the algorithm will find the element (or not) on its last check (when it's down to a list of length 1).

displaymath175

Obviously this is only going to work (in the sense that C(n/8), etc., make sense) if n is a power of 2. Assume that tex2html_wrap_inline212 , for integer m.

Consider a change of variable: in

displaymath176

we define tex2html_wrap_inline216 so that

displaymath177

Note that T(0)=C(1)=1. We can solve easily to get

displaymath178

Hence, tex2html_wrap_inline220 . This compares quite favorably with the worst-case estimate from SequentialSearch, which would be n (linear in n).

(For those of you who've forgotten, the tex2html_wrap_inline226 function grows much more slowly than a linear function.)

Let's look at the general recurrence relation of the ``divide and conquer'' variety: given

displaymath179

Assume tex2html_wrap_inline212 for some integer m. Then

displaymath180

Now we perform the change of variables: let tex2html_wrap_inline232 , so that

displaymath181

Using formula (8) of section 2.4, p. 134, we get

displaymath182

Then reindexing, since we start with 0 rather than 1, we get

displaymath183

Finally, substituting back in S and n, we get

displaymath184

Whew!

The BinarySearch algorithm starts with a sorted list, which is not a requirement for the SequentialSearch algorithm; so the comparison isn't really fair. What if we add a sort?

Example: (Exercise 11/13, p. 154/156)

Example: (Exercise 12/14, p. 154/156)

Example: (Exercise 13/15, p. 154/156)

Example: (Exercise 14/16, p. 154/156)

So we can carry out the BinarySearch algorithm following a MergeSort with

displaymath185

or

displaymath186

operations, compared with n operations for SequentialSearch - which wins in this case!

If we had started with a sorted list, however, it would make no sense to use SequentialSearch, since BinarySearch is so much more efficient.

Other criteria

An algorithm should not be analyzed quite so one-dimensionally as we've done here, of course: there may be other issues (such as how easily parallelized an algorithm is, for example) which are more important than simple operation counts.

As demonstrated in the case of the Euclidean Algorithm (or gcd) in this section, we may simply be shooting for an upper bound on the number of operations required (even worse than the worst case scenario!), when actual worst-case numbers are hard to come by.



LONG ANDREW E
Tue Oct 1 18:18:29 EDT 2002