Very often we are not interested in the actual function that describes the (time) complexity of an algorithm, but just in its complexity class. This basically tells us about the growth of the complexity function, and therefore something about the performance of the algorithm on large numbers of items.
Before we define complexity classes in a more formal manner, let us
first gain some intuition for what they actually mean. For this
purpose, we choose one function as representative for the
classes we wish to consider. We shall see in the next section to which
degree a representative can be considered `typical' for its class.
(Recall that we are considering functions which map natural numbers
(the size of the problem) to the set of real numbers
.)
The most common classes (in rising order) are the following:
As a representative, we choose the function which gives the class its
name--ie. for
we choose the function
,
also written as
, and for
we choose
, also written as
(this is the
logarithm to base
). So assume we have algorithms with these
functions describing their complexity. In the table below we list how
many operations it will take them to deal with a problem of a given
size.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
These numbers get so big that it is somewhat difficult to decide just
how long a time span they would describe. Hence here's a table which
gives time spans rather than instruction counts, based on the
assumption that we have a computer which can operate at a speed of
MIP, where one MIP = a million instructions per second.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
As we can see, if the size of our problem gets really big, there is a
huge difference in the time it takes to perform an algorithm of a
given class. This is why complexity classes are so important--they
tell us how feasible it is to run a program with a big number of data
items. Typically, people do not worry much about complexity below the
sizes of
or maybe
, but the above numbers should tell you
why it is worth thinking about complexity classes where bigger
applications are concerned.
Another useful way of thinking about growth classes is thinking about what happens if the problem size doubles. These considerations are given in the following table:
| If the size of the problem doubles then |
||
| the same, |
|
|
|
|
almost the same, |
|
| more by |
|
|
| twice as big as before, |
|
|
| a bit more than twice as big as before, |
|
|
| four times as big as before, |
|
|
| nine times as big as before, |
|
|
| the square of what it was before, |
|
We now give a plot of some of the functions from the table. Note that although these functions are only defined on natural numbers, we draw them as if they were defined for all real numbers, because that makes it easier to take in the information presented.