我正在尝试阻止对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
答案 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
开始,这将充分利用这些知识。