合并排序错误:分段错误

时间:2018-05-08 10:01:42

标签: c algorithm sorting mergesort array-algorithms

我收到错误Segmentation Fault:11,请帮忙。 变量信息:(s:start,e:end,m:mid,n:array),测试样本数组n[] = {4,3,2,1}a1a2是临时数组。我猜测有m:mid的计算并传递它。

#include <stdio.h>

void merge(int s, int e, int m, int n[]) {
    int l1 = m - s;
    int l2 = e - m + 1;
    int a1[l1];
    int a2[l2];
    for (int i = 0; i < l1; i++) {
        a1[i] = n[s + i];
    }
    for (int j = 0; j < l2; j++) {
        a2[j] = n[s + m + j];
    }

    int i = 0, j = 0; 
    for (int k = 0; k < l1 + l2; k++) {
        if (a1[i] <= a2[j] && i != l1 && j != l2) {
            n[k] = a1[i];
            i++;
        } else if (a2[j] <= a1[i] && i != l1 && j != l2) {
            n[k] = a2[j];
            j++;
        } else if (j == l2 && i != l1) {
            n[k] = a1[i];
            i++;
        } else if(i == l1 && j != l2) {
            n[k] = a2[j];
            j++;
        }
    }
}

void mergeSort(int s, int e, int n[]) {
    if (s < e) {
        int m = (e - s) / 2;
        mergeSort(s, m - 1, n);
        mergeSort(m, e, n);
        merge(s, e, m, n);
    }
}

int main(void) {
    int n[] = { 4, 3, 2, 1 };
    int r = 4;
    mergeSort(0, r - 1, n);

    for(int i = 0; i < r; i++) {
        printf("%i\n", n[i]);
    }
}

3 个答案:

答案 0 :(得分:0)

我已经在几个地方修改了你的代码。尝试使用您的调试器或笔&amp;用纸来了解幕后发生的事情。

void merge(int s, int e, int m, int n[]){

    int l1 = m-s + 1;
    int l2 = e - m;
    int a1[l1];
    int a2[l2];
    for(int i = 0; i < l1; i++){
        a1[i] = n[s+i];
    }
    for(int j = 0; j < l2; j++){
        a2[j] = n[m+j + 1];

    }


    int i = 0, j = 0; 
    for(int k = 0; k < l1+l2; k++){
        if(a1[i] <= a2[j] && i != l1 && j != l2){
            n[k] = a1[i];
            i++;
        }else if(a2[j] <= a1[i] && i != l1 && j != l2){
            n[k] = a2[j];
            j++;
        }else if(j == l2 && i != l1){
            n[k] = a1[i];
            i++;
        }else if(i == l1 && j != l2){
            n[k] = a2[j];
            j++;
        }
    }

}
void mergeSort(int s, int e, int n[]){
        if(s<e){
            int m = s + (e-s)/2;
            mergeSort(s, m, n);
            mergeSort(m + 1, e, n);
            merge(s,e,m, n);
}

我猜你会好的。

答案 1 :(得分:0)

由于无限递归调用,我认为你有一个stack overflow问题。看

void mergeSort(int s, int e, int n[]){
    if(s<e){
        int m = (e-s)/2;
        mergeSort(s, m-1, n);
        mergeSort(m, e, n);
        merge(s,e,m, n);
    }

}

您传递了se

的这些值
s e function
-------------
0 3 mergeSort
    0 0 mergeSort -> end
    1 3 mergeSort
        0 0 mergeSort -> end
        1 3 mergeSort
            ... (infinite calls)

然后,当新函数被调用时,堆栈会增长并增长,直到它最终超过可能的最大大小,从而导致SEGFAULT。

答案 2 :(得分:0)

中间元素的m计算是假的:你从m得到s的偏移量,而不是它在数组中的索引。

以下是更正后的版本:

void mergeSort(int s, int e, int n[]) {
    if (s < e) {
        int m = s + (e - s + 1) / 2;
        mergeSort(s, m - 1, n);
        mergeSort(m, e, n);
        merge(s, e, m, n);
    }
}

您的代码中还存在其他问题,尤其是:

  • 您应该先检查偏移ij dereferencing a1 [i] and a2 [j]`。
  • 不应在合并阶段直接使用偏移k,您应该存储到n[s + k]
  • a2的初始化循环中,您应该使用a2[j] = n[m + j];代替a2[j] = n[s + m + j];

另请注意,在包含第一个索引且排除最后一个索引的情况下传递C中的范围是惯用的。这允许传递空范围,而当前方法不会。它还使代码更简单,更易于阅读。

以下是修改后的版本:

#include <stdio.h>

void merge(int s, int e, int m, int n[]) {
    int l1 = m - s;
    int l2 = e - m;
    int a1[l1];
    int a2[l2];

    for (int i = 0; i < l1; i++) {
        a1[i] = n[s + i];
    }
    for (int j = 0; j < l2; j++) {
        a2[j] = n[m + j];
    }
    for (int i = 0, j = 0, k = 0; k < l1 + l2; k++) {
        if (i < l1 && (j >= l2 || a1[i] <= a2[j])) {
            n[s + k] = a1[i];
            i++;
        } else {
            n[s + k] = a2[j];
            j++;
        }
    }
}

void mergeSort(int s, int e, int n[]) {
    if (e > s + 1) {
        int m = s + (e - s) / 2;
        mergeSort(s, m, n);
        mergeSort(m, e, n);
        merge(s, e, m, n);
    }
}

int main(void) {
    int n[] = { 4, 3, 2, 1 };
    int r = sizeof(n) / sizeof(n[0]);
    mergeSort(0, r, n);

    for(int i = 0; i < r; i++) {
        printf("%i\n", n[i]);
    }
    return 0;
}