简体   繁体   English

部分插入排序

[英]Partial Insertion Sort

Is it possible to sort only the first k elements from an array using insertion sort principles? 是否可以使用插入排序原则对数组中的前k元素进行排序?

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} 原始数组:{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) k = 3预期输出:{1、2、3、5、8、6、8、3、10}(仅对前k个元素进行了排序,其余元素未排序)

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 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;
      } 
  }

Yes, it is possible. 对的,这是可能的。 This will run in time O(kn) where n is the size of your array. 这将在时间O(kn)中运行,其中n是数组的大小。

You are better off using heapsort. 您最好使用堆排序。 It will run in time O(n + k log(n)) instead. 它将在时间O(n + k log(n)) The heapify step is O(n) , then each element extracted is O(log(n)) . 堆化步骤为O(n) ,则提取的每个元素为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-1 th elements below the ni th one. 因此,当您将其视为树时,请将第n-2i, n-2i-1个元素放在第ni个元素之下。 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. 等等。

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. 万一将来有人需要它,我想出了一种“纯粹的”解决方案,从某种意义上说,它不是原始的Insertion排序与某些其他排序算法之间的混合体。

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. 基本上,此算法对前k个元素进行排序。 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. 然后,第k个元素就像一个枢轴:仅当其余数组元素小于此枢轴时,才像原始算法一样将其插入到已排序的k个元素之间的校正位置。

Best case scenario: array is already ordered 最佳情况:阵列已订购

Considering that comparison is the basic operation, then the number of comparisons is 2n-k-1 → Θ(n) 考虑到比较是基本操作,则比较次数为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) 考虑到比较是基本操作,则比较次数为(2kn - k² - 3k + 2n)/2 →Θ(kn)

(Both take into account the comparison made to maintain the array order) (两者都考虑了保持阵列顺序的比较)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM