为什么这个mergesort算法不起作用?

时间:2014-12-21 17:54:02

标签: c algorithm sorting mergesort

我在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);

}

有人可以解释这是一个错误,还是我没有正确处理内存分配?

1 个答案:

答案 0 :(得分:2)

  • 更改merge()函数的条件

while ((i1!=0) || (i2!=0))

while ((i1>0) || (i2>0))

它将删除段错误。

说明: 假设i1=0i2=1。然后看看会发生什么:

if (i1==0) {
        while ((i2--)!=0)
            *sorted++=*right++;
    }

当编译器检查i2时它是1.所以条件true。循环继续,i2递减1。所以现在i2=0
在下一次迭代中,当编译器再次检查i2时为0.条件false。循环中断,当您看到i21递减时。所以i2变为i2=-1。因为首先编译器检查i2然后递减。

所以这个while ((i1!=0) || (i2!=0))条件永远不会满足,并且* sorted ++不断增加,并在你的堆栈空间不足时导致segmfault。

  • 现在更改mergesort()函数的第一个条件。

那是:

if (N==1) { 
    *unsorted=*sorted;
    return 1;
}

if (N==1) {
    *sorted=*unsorted;
    return 1;
}

说明:如果您执行第一个,排序的数组将永远不会更改,您将永远不会获得排序输出。因此,当只剩下1个元素时,我们可以简单地将未排序数组的元素复制到已排序的元素。

我认为这样可以解决问题:)