【问题标题】:can't find the error in this mergesort program in c..always shows segmentation fault在 c 中的这个合并排序程序中找不到错误。总是显示分段错误
【发布时间】:2017-07-20 12:30:42
【问题描述】:

我在 C 中的这个 Mergesort 程序中找不到错误。 它总是显示分段错误。

这是我的合并排序代码:

我认为问题可能出在这里:

void merge(int *a, int i, int mid, int n) {
    int l, m, k, b[10];

    l = i;
    m = mid + 1;
    k = 0;

    while (l <= mid && m <= n) {
        if (a[l] > a[m])
            b[k++] = a[l++];

        if (a[m] > a[l])
            b[k++] = a[m++];
    }

    while (l <= mid)
        b[k++] = a[l++];

    while (m <= n)
        b[k++] = a[m++];

    for (k = 0; k < n; k++)
        a[i++] = b[k];

    return ;
}

【问题讨论】:

  • 你的第二个 while 循环没有花括号
  • 使用gcc 中的-ggdb3 标志重新编译您的代码,并在像gdb 这样的调试器中运行它。然后您可以backtrace 到源代码中段错误的位置。
  • 仅仅因为您认为问题可能出在您的部分代码中的某个模糊位置,并不意味着您应该只发布该部分。如果问题不存在,那么仅发布它根本没有用。发布不完整的代码并期望人们猜测其余部分的作用并不完全礼貌。您应该发布编译程序所需的最少代码量。这不是那个。
  • @ja08prat while 循环中只有一个语句,所以我觉得没有必要......
  • @underscore_d 我发布了整个代码,但 id 并没有让我因为代码部分太多它显示了我发布这部分的原因,因为它与其余部分一样有最大的错误机会部分是调用合并函数并将数组分成更小的数组

标签: c sorting merge segmentation-fault


【解决方案1】:

在您的功能即将结束时(以及其他地方......):

for(k=0;k<n;k++)   // k = [0 -> n)
    a[i++]=b[k];   // but b is declared as int b[10], this is surely not right.

上面的循环意味着您期望b 在某个时候准确地保存n 元素。为什么“b”的大小不合适?

【讨论】:

  • 但 b[10] 只是为了声明数组,以便我可以将排序的元素添加到其中,如果使用 b[10],这仅意味着数组大小为 10,但我不是担心尺寸,就好像在那之前终止我的循环一样,即直到我的父数组的最后一个索引 a[]...........我错了吗?
  • 10 还不够大。如果 n > 10 则保存 n 个元素。无论您打算做什么,它都太小了。
【解决方案2】:

您的代码存在多个问题:

  • mid 参数似乎是左半部分最后一个元素的索引,n 似乎是右半部分最后一个元素的索引。这与 C 中的常见做法不一致,i 是左半部分的索引,mid 应该是右半部分第一个元素的索引,n 应该是超出第一个元素的索引右半边。这样,通过从最后一个元素之外的索引中减去初始索引,可以轻松计算数组长度。

  • b 在本地分配为大小为10 的数组。如果要合并的块的大小大于 10,这是不正确的。您可以使用 malloc() 分配 (n - i) 元素的数组,或者如果要排序的数组的大小定义一个本地数组 int b[n - i];不太大(现代 64 位环境的条目少于 100 万个)。

  • l 是一个糟糕的局部变量名称选择:它在图形上与1 太接近,从而造成潜在的错误和混乱。

  • 主合并循环中的测试既多余又不完整:您没有处理左半部分元素等于右半部分元素的情况。

  • 最后一个循环,将合并的数据复制回源数组是有缺陷的:它应该是:

    for (k = 0; k < n - i; k++)
        a[i++] = b[k];
    

这是一个针对中等小数组的修正版本:

void merge(int *a, int start, int mid, int end) {
    int i, j, k, b[end - start];

    i = start;
    j = mid;
    k = 0;

    while (i < mid && j < n) {
        if (a[i] <= a[j])
            b[k++] = a[i++];
        else
            b[k++] = a[j++];
    }
    while (i < mid) {
        b[k++] = a[i++];
    }
    while (j < n) {
        b[k++] = a[j++];
    }
    for (i = start, k = 0; i < end; i++, k++) {
        a[i] = b[k];
    }
}

void mersort(int *a, int length) {
    if (length > 1) 
        int mid = length / 2;
        mergesort(a, mid);
        mergesort(a + mid, length - mid);
        merge(a, 0, mid, length);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 2021-03-24
    • 2017-01-11
    • 2020-05-25
    相关资源
    最近更新 更多