【问题标题】:why doesn't this mergesort algorithm work? [closed]为什么这个归并排序算法不起作用? [关闭]
【发布时间】:2014-12-21 17:54:01
【问题描述】:

我在 C 中尝试了以下代码用于合并排序,但它最终给了我一个段错误。有人能找到错误吗?

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

}

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

【问题讨论】:

  • @hatchet:OP 说它抛出了一个段错误。
  • 你能告诉我们段错误发生在哪一行吗?并给我们一个引发段错误的输入示例?
  • mergesort 是一个递归函数,具有非常大的堆栈帧 (4 * MAXLEN * sizeof(int));可能你的堆栈空间用完了。要验证这一点,请使用stack overflow checking 编译并重新测试。
  • 您错过了N &lt;= 0,可能想查看1 == N 的案例。 Ruud 指出了您的实现使用的内存量,让我补充一点,比输入大小更多的额外内存是浪费的。如果您不想修改某些内容,请让维护编码器/编译器知道:int mergesort(int const * unsorted, …。您的fill() 副本 - 名称应反映您眼中的重要内容。使用tool 记录文档。

标签: c algorithm sorting mergesort


【解决方案1】:
  • 改变merge()函数的条件

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

while ((i1&gt;0) || (i2&gt;0))

它将删除段错误。

说明: 假设i1=0i2=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。

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

即:

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

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

解释:如果你做第一个,排序后的数组永远不会改变,你也永远不会得到排序后的输出。因此,当只剩下 1 个元素时,我们可以简单地将未排序数组的元素复制到已排序。

我认为这会解决问题:)

【讨论】:

  • 如果您能解释为什么您认为这些将解决段错误问题,那将会有所帮助。 (教人钓鱼……)
  • 强调:使用while (not ready) ((0 &lt; --i)) 代替while (not(first beyond))
  • 总是很开心 :)
猜你喜欢
  • 1970-01-01
  • 2019-11-12
  • 1970-01-01
  • 2017-11-29
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 2021-07-06
相关资源
最近更新 更多