Partial Insertion Sort

1.4k Views Asked by At

Is it possible to sort only the first k elements from an array using insertion sort principles?

Because as the algorithm runs over the array, it will sort accordingly.

Since it is needed to check all the elements (to find out who is the smallest), it will eventually sort the whole thing.

Example:

Original array: {5, 3, 8, 1, 6, 2, 8, 3, 10}

Expected output for k = 3: {1, 2, 3, 5, 8, 6, 8, 3, 10} (Only the first k elements were sorted, the rest of the elements are not)

3

There are 3 best solutions below

0
On BEST ANSWER

Such partial sorting is possible while resulting method looks like hybrid of selection sort - in the part of search of the smallest element in the tail of array, and insertion sort - in the part of shifting elements (but without comparisons). Sorting preserves order of tail elements (though it was not asked explicitly)

Ideone

void ksort(int a[], int n, int k)
  { int i, j, t;
    for (i = 0; i < k; i++)
      { int min = i;
        for (j = i+1; j < n; j++) 
            if (a[j] < a[min]) min = j;
        t = a[min];
        for (j = min; j > i; j--) 
            a[j] = a[j-1];
        a[i] = t;
      } 
  }
1
On

Yes, it is possible. This will run in time O(k n) where n is the size of your array.

You are better off using heapsort. It will run in time O(n + k log(n)) instead. The heapify step is O(n), then each element extracted is O(log(n)).

A technical note. If you're clever, you'll establish the heap backwards to the end of your array. So when you think of it as a tree, put the n-2i, n-2i-1th elements below the n-ith one. So take your array:

{5, 3, 8, 1, 6, 2, 8, 3, 10}

That is a tree like so:

 10
     3
         2
             3
             5
         6
     8
         1
         8

When we heapify we get the tree:

 1
     2
         3
             3
             5
         6
     8
         10
         8

Which is to say the array:

{5, 3, 8, 10, 6, 3, 8, 2, 1}

And now each element extraction requires swapping the last element to the final location, then letting the large element "fall down the tree". Like this:

# swap
{1*, 3, 8, 10, 6, 3, 8, 2, 5*}
# the 5 compares with 8, 2 and swaps with the 2:
{1, 3, 8, 10, 6, 3, 8?, 5*, 2*}
# the 5 compares with 3, 6 and swaps with the 3:
{1, 3, 8, 10, 6?, 5*, 8, 3*, 2}
# The 5 compares with the 3 and swaps, note that 1 is now outside of the tree:
{1, 5*, 8, 10, 6, 3*, 8, 3, 2}

Which in a array-tree representation is:

{1}
2
    3
        3
             5
        6
    8
       10
        8

Repeat again and we get:

# Swap
{1, 2, 8, 10, 6, 3, 8, 3, 5}
# Fall
{1, 2, 8, 10, 6, 5, 8, 3, 3}

aka:

{1, 2}
3
    3
        5
        6
    8
       10
        8

And again:

# swap
{1, 2, 3, 10, 6, 5, 8, 3, 8}
# fall
{1, 2, 3, 10, 6, 8, 8, 5, 3}

or

{1, 2, 3}
3
    5
        8
        6
    8
       10

And so on.

0
On

Just in case anyone needs this in the future, I came up with a solution that is "pure" in the sense of not being a hybrid between the original Insertion sort and some other sorting algorithm.

void partialInsertionSort(int A[], int n, int k){
    int i, j, aux, start;
    int count = 0;
    for(i = 1; i < n; i++){
        aux = A[i];

        if (i > k-1){
            start = k - 1;
            //This next part is needed only to maintain
            //the original element order
            if(A[i] < A[k])
                A[i] = A[k];
        }
        else start = i - 1;

        for(j = start; j >= 0 && A[j] > aux; j--)
                A[j+1] = A[j];

        A[j+1] = aux;
    }
}

Basically, this algorithm sorts the first k elements. Then, the k-th element acts like a pivot: only when the remaining array elements are smaller than this pivot, it is then inserted in the corrected position between the sorted k elements just like in the original algorithm.

Best case scenario: array is already ordered

Considering that comparison is the basic operation, then the number of comparisons is 2n-k-1 → Θ(n)

Worst case scenario: array is ordered in reverse

Considering that comparison is the basic operation, then the number of comparisons is (2kn - k² - 3k + 2n)/2 → Θ(kn)

(Both take into account the comparison made to maintain the array order)