在c..always显示分段错误中找不到此mergesort程序中的错误

时间:2017-07-20 12:30:43

标签: c sorting merge segmentation-fault

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

这是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 ;
}

2 个答案:

答案 0 :(得分:0)

接近你的功能的结尾(在其他地方..):

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'尺寸不合适?

答案 1 :(得分:0)

您的代码中存在多个问题:

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

  • b在本地分配为大小为10的数组。如果要合并的块的大小大于10,则这是不正确的。您可以使用(n - i)分配malloc()个元素的数组,或者如果大小,则定义本地数组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);
    }
}