The order of a function T(N) is a description of its rate of growth as N becomes very large.
When analyzing the order of algorithms, the following definitions are commonly used:
As an example, if T(N) = 2N + 1, then T(N) = O(N). To prove this, all we need to do is find c and such that when . If we try c = 3, then we can subtract 2N from both sides of the inequality and get . This is clearly true when , so is 1.
It may seem strange that in this case f(N) is clearly less than T(N) for all positive values of N, and yet T(N) = O(f(N)). The actual values of T(N) and f(N) are not the issue- the important issue is whether a c and can be found that satisfy this rule.
This is similar to the big-O notation, but from the other direction- the order of f(N) is typically as large as possible without making it larger than the order of T(N).
As an example, if T(N) = 2N + 1, then T(N) = O(N). To prove this, once again all we need to do is find c and such that when . If we try c = 2, then we can subtract 2N from both sides of the inequality and get . This is clearly true for any N.
Remember that in this notation, our goal is to find f(N) (an order), given T(N) (a function). For example, imagine that we have a function , and we would like to say things about it using big-O notation. It is correct to say ``g(N) is '' but it is usually not correct to say ``O(g(N)) is ''.
It may seem strange that the order of f(N) might actually be greater than the order of T(N). For example, if , then it is also true that , and so on.
By general convention, f(N) is chosen to be the smallest order that is known to be greater or equal to the order of T(N). In this example, you would never say that if you knew that . It would be correct, at least in a mathematical sense, but potentially very misleading to the reader. In fact, in many contexts, big-O is used synonymously with big-theta.
As another convention, any constant factors are dropped from the order. For example, according to the definition given above, it is true that . However, it is also true that . The latter form, where the constant factor has been omitted, is the standard way of expressing the big-O of a function.
Similarly, it is also a convention to drop all but the ``largest'' term of the order. The largest term is the dominant term (see section 2.2.1 for more information). For example, , since as n becomes large, the quadratic term will grow more quickly than the others.
At first glance, it would appear that is all we really want or need- after all, it's the ``right'' answer, where the order of T(N) is exactly f(N). If we know the real order of T(N), then we know .
Unfortunately, life is not so simple. Consider the following code snippet:
1 void strange1 (int A[N]) 2 { 3 int i; 4 5 for (i = 0; i < N; i++) { 6 if (A[N] == 0) { 7 break; 8 } 9 printf ("A [%d] = %d\n", i, A[i]); 10 } 11 }
What is the order of strange1? It is impossible to know without knowing what the contents of array A are: if there is always a zero element in the array, and the first zero element is always at a fixed location in this array (for example, the first location), then this function is - it always takes the same amount of time to run, regardless of N. If we know that there isn't a zero element anywhere in the array, then this algorithm is , since it visits every location in the array, and the array is of length N. If we don't know anything about the contents of the array, however, then we can't be sure what the order is, so we don't know what the true order of is. We know that the order is no less than order 1, so . Similarly, we know that the order is no larger than N, so .