使用带有预分隔间隔的mergesort

时间:2014-02-19 07:24:15

标签: c algorithm sorting mergesort

我正在尝试阻止对mergesort进行任何不必要的递归调用,因为我的数组是按部分预分类的,例如:

22, 233, 445, 1055, 1, 14, 94, 74545, 75, 134, 323, 9090, 2, 43, 6342, 323452

我正在使用通用mergesort实现

void merge(int a[], int low, int mid, int high)
{
    int b[10000];
    int i = low, j = mid + 1, k = 0;

    while (i <= mid && j <= high) {
        if (a[i] <= a[j])
            b[k++] = a[i++];
        else
            b[k++] = a[j++];
    }
    while (i <= mid)
        b[k++] = a[i++];

    while (j <= high)
        b[k++] = a[j++];

    k--;
    while (k >= 0) {
        a[low + k] = b[k];
        k--;
    }
}

void mergesort(int a[], int low, int high)
{
    if (low < high) {
        int m = (high + low)/2;
        mergesort(a, low, m);
        mergesort(a, m + 1, high);
        merge(a, low, m, high);
    }
}

如果我的程序知道每4个元素已经排序,我怎样才能将mergesort修改为 start 从4的已排序组合并而不是将数组分解为单个元素部分然后开始合并?

示例:

22,233,445,1055     1,14,94,74545,     75,134,323,9090     2,43,6342,323452
      \                  /                    \                   /
       \                /                      \                 /
   1,14,22,94,233,445,1055,74545        2,43,75,134,323,6342,9090,323452
              \                                           /
               \                                         /
        1,2,14,22,43,75,94,134,233,323,445,1055,6342,9090,74545,323452  

1 个答案:

答案 0 :(得分:3)

您实现的是Top-down mergesort,这意味着将数组拆分为两部分,对每个部分进行排序,然后将它们合并在一起。这是递归完成的。它的问题是,假设数组有12个元素,那么它会将数组拆分成2个6元素数组,这样就不会有每4个元素已经排序的事实。

您应该使用Bottom-up mergesort,即将数组拆分为子数组,每个子数组都有4个元素。由于它们中的每一个都已经排序,因此将每两个子数组合并为8个元素的子数组,然后将每两个8元素子数组合并为16个元素的子数组,依此类推。排序N元素数组的代码如下:

for (int sz = 1; sz < N; sz = sz+sz)
    for (int lo = 0; lo < N-sz; lo += sz+sz)
        merge(a, lo, lo+sz-1, min(lo+sz+sz-1, N-1)); 

由于您已经知道每4个元素都已排序,因此您可以从sz 4开始,这将充分利用这些知识。