When we analyze algorithms, we make a couple of assumptions:
The key thing we have to figure out is the number of iterations of the inner loop.
|
So the total time is:
[c1 + (n-1)c2] + [c1 + (n-2)c2] +
[c1 + (n-3)c2] + ... + [c1 +
(1)c2]
We have n-1 terms, each of the form c1 + (...)c2.
Total time = (n-1)c1 + [(n-1) + (n-2) + (n-3) + ... +
1]c2.
What is 1 + 2 + 3 + ... + (n-1)?
1 + 2 + 3 + ... + n = = n(n + 1) / 2 .
This is known as an arithmetic series.
So, 1 + 2 + 3 + ... + n-1 = ((n-1) * n) / 2 = (n2 - n) / 2 =
O(n2)
Therefore, total time is (n-1)c1 + c2 *
O(n2) = O(n2)
This result is independent of the input
characteristics.
Works like sorting a hand of cards - you place A[i] where it belongs in A[0..i] so that A[0..i] is sorted.
|
At iteration i, A[0..i-1] is the original A[0..i-1], but sorted. We place A[i] where it belongs in A[0..i], so that now A[0..i] becomes sorted.
See insertionSort.cpp.
Outer loop runs i = 1 to n - 1 ==> O(n)
Inner loop runs between 0 and i times ==> O(n)
Total is O(n) * O(n) = O(n2)
But remember that here O(n2) is only an upper bound. Can the running time be less?
Inner loop runs 0 times ==> O(n) total time for the algorithm. This occurs when the array is already sorted. The closer to sorted the input is, the faster insertion sort runs. Times when input might be "almost" sorted could include the way checks you write arrive at your bank. Some may take longer to get back than others, but they will mostly arrive in numerical order (assuming, of course, that you write them in numerical order)
Inner loop runs i/2 times. This reduces the worst case time by 1/2, but it's still O(n2). This is an example of how the average case often isn't much better than the worst case.
To Index Previous Next