1

I got a insertion sort algorithm below, it includes the nested for loop:

public InsertionSort( AnyType [] a ){
    int m; 
    for( int n = 1; n < a.length; n++ ){
        AnyType temp = a[n];
        for( m = n; m > 0 && tmp.compareTo( a[ m - 1] ) <= 0; m-- )
            a[ m ] = a[ m - 1 ];
        a[ m ] = temp;  
    } 
} 

The first loop has running time O(N) and the second is O(N^2), so the total running time in nested loop should be O(N*N^2=N^3), am I right? But I know the fact that worst case should be O(N^2) in insertion sort, however my teacher changed this segment of code that book provides a little bit by replacing a[ m - 1] ) <= 0, instead of using a[ m - 1] ) < 0. So I'm confused that how come I calculate a case worse than the worst case. Anyone helps? Thanks in advance.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Student
  • 45
  • 1
  • 2
    The second loop also looks `O(N)` to me, which would give the expected `O(N^2)` overall performance for insertion sort. – Tim Biegeleisen Nov 11 '16 at 01:58
  • But if I try sort a array which has all same elements, the number of comparisons and swaps are all 1+2+3+...n-1 times till the sort ended, so I get n(n-1)/2 = O(n^2) – Student Nov 11 '16 at 02:13
  • And this is not the traditional code for insertion sort, my teacher changed a little by replacing a[ m - 1] ) <= 0, instead of using a[ m - 1] ) < 0. – Student Nov 11 '16 at 02:17
  • The fact the _condition_ of the inner loop is different has no effect on the upper bound, which is at most covering each element in the array, hence making it `O(N)`. – Tim Biegeleisen Nov 11 '16 at 02:51

3 Answers3

1

the second is O(N^2)

That is wrong. See how.

Considering a.length = N, TC should be O(N^2).

Because (1 + 2 + 3 + ... + N-1) = N(N-1)/2 = O(N^2)

Inner loop runs 1 time more than previous time.

[1, 1]
[2, 1]
[3, 1]
...
[N-1, 1]
Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
0

for( int n = 1; n < a.length; n++ ){

In this above line, you are going through the array n - 1 times (since you are starting at index 1 all the way to a.length -1), thus O(N)

for( m = n; m > 0 && tmp.compareTo( a[ m - 1] ) <= 0; m-- )

In this inner loop, you are starting at n and then moving downwards, so in the WORST case, you will be going from the current value n all the way down to 1, thus performing up to n comparisons.

Therefore, we can see the following in the WORST case:

  • First iteration: you are going from 1 to 1
  • Second iteration: you are going from 2 to 1
  • Third iteration: you are going from 3 to 1
  • ...
  • N-1th iteration: you are going from N -1 to 1

Therefore, you are performing 1 + 2 + 3 + 4 + ... N - 1 operations in total which equals to:

(N)(N-1)/2 = O(N^2)

cullan
  • 280
  • 3
  • 13
0

Let's make that code simpler like below.

public InsertionSort( AnyType [] a ){
    // A value n
    for( ; n < length ; ){
        // A value m
        for( ; m < someLength ; ) {
            // do something.
        }
    } 
}

As you said, 'someLength' can be 1 from n-1.

But Let's see that code in the inner loop aspect.

    blahblah
        for( ; m < someLength ; ) {
            // do something.
        }
    blahblah

It runs only someLength - m ( or none if it's under 0 ) times

, which is linear

, which is represented as N( for O(N) ).


One more thing.

1+2+3+4+...+n-1 can't be occured without outer loop, can it?

Then why do you count them for the inner loop's complexity?

Al.T.Os
  • 72
  • 9