【问题标题】:merge sort in the book introduction to algorithms, 3rd edition not working for memerge sort in the book introduction to algorithms, 3rd edition not working for me
【发布时间】:2022-12-01 20:30:08
【问题描述】:

i can't understand the problem in my code, can anyone explain to me where the problem in my code please. the book where i got my algorithm:Introduction to Algorithms, Third Editioni understand how the algorithm work but in coding it, its sort only the 4 first number and keep the other without sorting.

code:

`

#include <stdio.h>
void sortArr(int *nums,int arrSize){
// nums[start...end]
// nums[start...mid]  n1
// nums[mid+1...end]  n2
    int start, mid, end;
    start = 0;
    end = arrSize-1;
    mid = (end+start)/2;
    int n1, n2;
    n1 = mid-start+1;
    n2 = end - mid;
    int l[n1], r[n2];
    for(int i=0;i<n1;i++){
        l[i] = nums[start+i];
    }
    for(int i=0;i<n2;i++){
        r[i] = nums[mid+1+i];
    }
    int i, j;
    i =0;
    j = 0;
    for(int k=start;k<arrSize;k++){
        if(l[i]<=r[j]){
            nums[k] = l[i];
            i++;
        }else{
            nums[k] = r[j];
            j++;
        }
    }
}
int main(){
    int arr[] = {3, 41, 52, 26, 38, 57, 9, 49};
    int arrsize = sizeof(arr)/sizeof(arr[0]);
    printf("before sorting: \n");
    for(int i=0;i<arrsize;i++){
        printf("%d ", arr[i]);
    }
    sortArr(arr, arrsize);
    printf("\n after sorting: \n");
    for(int i=0;i<arrsize;i++){
        printf("%d ", arr[i]);
    }
    return 0;
}

`

【问题讨论】:

  • Debugger.......
  • Without looking at the code or the book: check array indexing! In pseudocode it often starts at 1, in C at 0.
  • I used the starting index in 0 and changed other index to work with the index 0 instead of 1
  • For mergesort, you need to sort the two halves before merging. And it's not your problem yet, but using a VLA for the two halves will only work for small arrays
  • Also your merge is wrong (it produces out-of-range reads) in the case when one of the two halves is used up. The algorithm in the book adds +infinity to both halves to prevent this, although this is not how I'd actually write it in C.

标签: c algorithm sorting mergesort


【解决方案1】:

Add this print command to the final loop: printf("%d %d %d ", k, i, j);

n1 = n2 = 4, so both arrays have values only up to index 3. Yet in the final loop, you run i from 0 to 6. This cannot work.

You can add more print commands, run the algorithm with pen and paper, and hopefully find the place where it went wrong.

【讨论】:

  • i understand now that's the last index in l[i] is i = 3 but in the loop its go to i=6 so that's totally wrong
  • arrSize is 8, and the last loop correctly goes from 0 (inclusive) to 8 (exclusive).
  • @PaulHankin That is the range for k, not i.
  • this book its driving me crazy, the insertion sort algorithm worked fine, but this... i think i should change to other algo books
【解决方案2】:

There's quite a few problems with your code, including the fact that you've only implemented MERGE from the book (a subroutine for MERGESORT), and the book uses a trick of appending +infinity to the "halves" of the array to avoid having code that handles when one of the halves is used up when merging.

Here's a working version based on the book algorithms. Compared to the code in the question, it also avoids the VLAs (variable length arrays) which are likely to fail on large input arrays, and uses the more correct size_t for array indexes.

The code adds some extra tests in the if statement for li and ri when merging which is a different way than the book's +infinity trick, and works better in C.

The functions return 1 if successful, and 0 if unsuccessful (which can happen if you give end less than start or malloc fails). Assertions are used to check assumptions about the various indexes and sizes -- these should fail only if there's a bug in the code and can be compiled out.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int MERGE(int *nums, size_t start, size_t mid, size_t end) {
    size_t n1 = mid - start + 1;
    size_t n2 = end - mid;
    assert(n1 > 0);
    assert(n2 > 0);
    int *L = malloc(n1 * sizeof(int));
    if (!L) return 0;
    int *R = malloc(n2 * sizeof(int));
    if (!R) {
        free(L);
        return 0;
    }
    for (size_t i = 0; i < n1; i++) {
        assert(start + i <= mid);
        L[i] = nums[start + i];
    }
    for (size_t i = 0; i < n2; i++) {
        assert(mid + 1 + i <= end);
        R[i] = nums[mid + 1 + i];
    }
    size_t li = 0, ri = 0;
    for (size_t i = 0; i <= end - start; i++ ){
        if (li < n1 && (ri == n2 || L[li] <= R[ri])) {
            assert(li < n1);
            nums[start + i] = L[li++];
        } else {
            assert(ri < n2);
            nums[start + i] = R[ri++];
        }
    }
    free(R);
    free(L);
    return 1;
}

int MERGESORT(int *nums, size_t start, size_t end) {
    if (end < start) return 0;
    if (end == start) return 1;
    size_t mid = start + (end - start) / 2;
    if (!MERGESORT(nums, start, mid)) return 0;
    if (!MERGESORT(nums, mid+1, end)) return 0;
    return MERGE(nums, start, mid, end);
}

int main(){
    int arr[] = {3, 41, 52, 26, 38, 57, 9, 49};
    size_t arrsize = sizeof(arr)/sizeof(arr[0]);
    printf("before sorting: 
");
    for(size_t i=0; i<arrsize; i++){
        printf("%d ", arr[i]);
    }
    printf("
");
    if (!MERGESORT(arr, 0, arrsize-1)) {
        printf("failed
");
        exit(1);
    }
    printf("after sorting: 
");
    for(size_t i=0; i<arrsize; i++){
        printf("%d ", arr[i]);
    }
    printf("
");
    return 0;
}

【讨论】:

    猜你喜欢
    • 2020-11-11
    • 2017-01-29
    • 2019-11-30
    • 2022-12-28
    • 2021-03-24
    • 2013-03-25
    • 2013-04-24
    • 1970-01-01
    • 2022-12-27
    相关资源
    最近更新 更多