我在C中尝试了以下用于mergesort的代码,但它最终给了我一个段错误。有人能找到这个错误吗?
int mergesort(int* unsorted, int* sorted, int N) {
if (N==1) {
*unsorted=*sorted;
return 1;
}
else {
int left[MAXLEN];
int right[MAXLEN];
int sleft[MAXLEN];
int sright[MAXLEN];
int k1 = fill(unsorted,left,0,N/2);
int k2 = fill(unsorted,right,N/2,N);
int l1 = mergesort(left,sleft,k1);
int l2 = mergesort(right,sright,k2);
merge(sorted,sleft,sright,l1,l2);
return N;
}
}
void merge(int* sorted,int* left,int* right,int N1,int N2) {
int i1=N1;
int i2=N2;
while ((i1!=0) || (i2!=0)) {
if (i1==0) {
while ((i2--)!=0)
*sorted++=*right++;
}
else if (i2==0) {
while ((i1--)!=0)
*sorted++=*left++;
}
else {
if (*left < * right) {
*sorted++=*left++;
i1--;
}
else {
*sorted++=*right++;
i2--;
}
}
}
}
填充功能已实现如下
int fill(int* from, int* to, int left, int right) {
int i = left;
from += i;
while (i<right) {
*to++=*from++;
i++;
}
return (right-left);
}
有人可以解释这是一个错误,还是我没有正确处理内存分配?
答案 0 :(得分:2)
while ((i1!=0) || (i2!=0))
到
while ((i1>0) || (i2>0))
它将删除段错误。
说明:
假设i1=0
和i2=1
。然后看看会发生什么:
if (i1==0) {
while ((i2--)!=0)
*sorted++=*right++;
}
当编译器检查i2
时它是1.所以条件true
。循环继续,i2
递减1
。所以现在i2=0
在下一次迭代中,当编译器再次检查i2
时为0.条件false
。循环中断,当您看到i2
按1
递减时。所以i2
变为i2=-1
。因为首先编译器检查i2
然后递减。
所以这个while ((i1!=0) || (i2!=0))
条件永远不会满足,并且* sorted ++不断增加,并在你的堆栈空间不足时导致segmfault。
那是:
if (N==1) {
*unsorted=*sorted;
return 1;
}
到
if (N==1) {
*sorted=*unsorted;
return 1;
}
说明:如果您执行第一个,排序的数组将永远不会更改,您将永远不会获得排序输出。因此,当只剩下1个元素时,我们可以简单地将未排序数组的元素复制到已排序的元素。
我认为这样可以解决问题:)