我创建了一个Merge排序,效率非常低,空间占用空间很大。每次递归调用都会创建一个新数组。在不影响我的函数参数的情况下,我可以创建一个动态数组,我只需要创建和删除一次吗?
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]);
}
答案 0 :(得分:1)
通常,仅使用n个额外空间的合并排序使用传递到merge()
和mergesort()
函数的辅助数组。然后,不是每次都创建一个新的辅助数组,而只是在当前merge()
调用中使用辅助数组中的相同索引 - 这样,所有merge()
调用都可以不踩对方的脚趾就做他们的事。
由于你的教授不会让你传递任何额外的参数,你将不得不做一些有点hacky能够使用辅助阵列的东西 - 我们将在末尾使用尽可能多的空间数组我们传入,就像我们为数组本身做的那样。请注意,这需要您传入一个正常的数组两倍,使用垃圾填充一半(我们只需要空间) - 它还需要一些额外的工作来确保您知道辅助数组的起始位置。
我将尽量避免给你提供准确的代码,因为这是作业 - 但我使用的想法(我只是在我的计算机上运行)是保留一个名为helper的全局变量,它是指向“数组的末尾(或辅助数组的开头)。然后,当您进入mergesort()
调用时,检查它是否已初始化 - 如果没有,则将其指向辅助数组的开头。除此之外,您的代码可以保持基本相同 - 但不是在每个合并函数的开头创建一个新数组helper[]
,只需使用全局代码。
如果有人有一个不涉及使用全局变量的解决方案,我会全力以赴 - 但在限制范围内,这是有效的。