合并排序与 n 个额外的空格

Merge sort with n extra space

本文关键字:空格 排序 合并      更新时间:2023-10-16

我创建了一个合并排序,由于额外的空间使用,效率非常低。每次递归调用都会创建一个新数组。 在不影响函数参数的情况下,我可以创建一个只需要创建和删除一次的动态数组吗?

void mergesort_normal(Item *A, int p, int r)
{
int middle;
if (p < r) {
middle = p + (r - p) / 2;
mergesort_normal(A, p, middle);
mergesort_normal(A, middle +1, r);
merge_normal(A, p, middle, r);
}
}
void merge_normal  (Item *A, int p, int mid, int r)
{
Item *helper = new Item[r+1];
int h = p;
int i = p;
int j = mid +1;
int k = 0;

while((h<=mid)&&(j<=r))
{
if(lessThan(A[h], A[j]))
{
helper[i]=key(A[h]);
h++;
}
else
{
helper[i]=key(A[j]);
j++;
}
i++;
}
if(h>mid)
{
for(k=j;k<=r;k++)
{
helper[i]=key(A[k]);
i++;
}
}
else
{
for(k=h;k<=mid;k++)
{
helper[i]=key(A[k]);
i++;
}
}
for(k=p;k<=r;k++)
A[k]=key(helper[k]);
}

通常,只有 n 个额外空间的合并排序使用传递到merge()mergesort()函数中的辅助数组。然后,您不必每次都创建一个新的帮助程序数组,而只需在帮助程序数组中使用与当前merge()调用中使用的索引相同的索引 - 这样,所有merge()调用都可以在不踩到彼此的脚趾的情况下完成它们的事情。

由于您的教授不会让您传入任何额外的参数,因此您将不得不做一些有点笨拙的事情才能使用辅助数组 - 我们将在数组末尾使用与数组本身一样多的空间。请注意,这需要您传入一个数组的两倍长,一半填充垃圾(我们只需要空间) - 它还需要一些额外的工作来确保您知道辅助数组从哪里开始。

我将尽量避免给你确切的代码,因为这是家庭作业 - 但我使用的想法(我刚刚在我的计算机上工作)是保留一个名为 helper 的全局变量,它是指向数组"结束"的指针(或辅助数组的开头)。然后,当您进入mergesort()调用时,检查它是否已初始化 - 如果没有,请将其指向辅助数组的开头。除此之外,您的代码可以基本保持不变 - 但不在每个合并函数的开头创建一个新的数组helper[],只需使用全局数组即可。

如果有人有一个不涉及使用全局变量的解决方案,我会全力以赴 - 但在限制范围内,这有效。