简体   繁体   中英

Merge Sort in C using Recursion

This is my code for merge sort in C. I'm not able to understand what the issue is here. My knowledge of pointers is not that much. The merge function takes in 2 arrays and merges them. the sort function is a recursive function which is supposed to sort the array.


int * merge(int *fir, int n, int *sec, int m){
    int res[m+n];
    int x=0, y=0;
    for(int i = 0; i < m+n; i++){
        if(*(fir+x)<=*(sec+y)){
            res[i] = *(fir+x);
            x++;
        }else{
            res[i] = *(sec+y);
            y++;
        }

    }
    return res;
}

int * sort(int A[], int n){
    if(n == 1){
        return A;
    }
    int mid = n/2;
    int AL[mid], AR[n-mid];
    for(int i = 0; i < mid; i++){
        AL[i] = A[i];
    }
    for(int i = 0; i < n-mid; i++){
        AR[i] = A[i+mid];
    }
    int *BL, *BR;
    BL = sort(AL, mid);
    BR = sort(AR, n-mid);
    return(merge(BL, mid, BR, n-mid));
}

int main(){
    int n;
    scanf("%d", &n);
    int A[n];
    for(int i = 0; i < n; i++){
        scanf("%d", &A[i]);
    }
    int *sortedArray;
    sortedArray = sort(A, n);
    for(int i = 0; i < n; i++){
        printf("%d ", *(sortedArray+i));
    }

    return 0;
}

And this is the output

q8.c:16:9: warning: address of stack memory associated with local variable 'res' returned [-Wreturn-stack-address]
        return res;
               ^~~
1 warning generated.
7
23 12 56 67 11 99 97
97 32766 539779418 32767 -2002825496 32767 6 %```

There are two issues here: First, you merge your partial arrays into a temporary local array, which yoes out of bounds after you return from merge . The pointer you return points to invlid memory. That's what the warning about.

Second, you don't check whether you are reading beyond the limits of the partial arrays when you merge: The condition x < n must be true when you access fir , likewise for y < m and sec .

You are also causing confusion by returning a pointer to the first element of the sorted or merged arrays. That suggests that you create new sorted and merged arrays (and that's what you try to do in merge ). This is okay for garbage-collected morern languages, but C doesn't work that way.

In C, if you need new memory, you must allocate it and later free it explicitly. In a recursive function like yours, this is tedious, because you are interested only in the final sorted array, not in the intermediate results. Therefore, C sorting algorithms usually work "in place": The same memory is used thoughout the sorting and elements are swapped. The original order of the elements is lost unless you make a copy before sorting.

For merge sort, you need auxiliary memory. In your case, you use the temporary arrays AL and AR , which are copies of the contents of the original array, A . Now when you merge, you can merge AL and AR back into A .

So istead of creating a ephemeral local array, pass in A so that it can be filled with the sorted elements:

void sort(int A[], int n)
{
    if (n > 1) {
        int mid = n / 2;
        int AL[mid], AR[n - mid];

        for (int i = 0; i < mid; i++) AL[i] = A[i];
        for (int i = 0; i < n - mid; i++) AR[i] = A[i + mid];
        
        sort(AL, mid);
        sort(AR, n - mid);
        
        merge(A, AL, mid, AR, n - mid);
    }
}

Your merge function is now very similar to the one you has before, only that you have the result array as parameter and that you must catch the out-of-bound cases before accessing elements with [] .

void merge(int *res, const int *fir, int n, const int *sec, int m)
{
    int x = 0, y = 0;

    for(int i = 0; i < m + n; i++) {
        if      (x == n)            res[i] = sec[y++];
        else if (y == m)            res[i] = fir[x++];
        else if (fir[x] <= sec[y])  res[i] = fir[x++];
        else                        res[i] = sec[y++];
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM