What is wrong in this implementation of merge sort?

我只是一个虾纸丫 提交于 2020-01-17 03:50:02

问题


I know that there are many implementations of merge sort but this is one which I have read in the book "Introduction to algorithms". The following code is an implementation of merge sort which is not working correctly:

#include <iostream>

using namespace std;
void merge(int*a, int p, int q, int r) {  //function to merge two arrays

  int n1 = (q - p);  // size of first sub array

  int n2 = (r - q);  // size of second subarray

  int c[n1], d[n2];

  for (int i = 0; i <= n1; i++) {
    c[i] = a[p + i];
  }

  for (int j = 0; j <= n2; j++) {
    d[j] = a[q + j];
  }

  int i = 0, j = 0;

  for (int k = p; k < r; k++) {  // merging two arrays in ascending order

    if (c[i] <= d[j]) {
      a[k++] = c[i++];

    } else {
      a[k++] = d[j++];

    }
  }
}

void merge_sort(int*a, int s, int e) {
  if (s < e) {
    int mid = (s + e) / 2;
    merge_sort(a, s, mid);
    merge_sort(a, mid + 1, e);
    merge(a, s, mid, e);
  }
}

int main() {
  int a[7] { 10, 2, 6, 8, 9, 10, 15 };
  merge_sort(a, 0, 6);
  for (auto i : a)
    cout << i << endl;
}

This code is not working correctly. What's wrong in this code? How can it be fixed?


回答1:


There are couple of things gone wrong in the implementation of your logic. I have indicated them clearly below:

void merge(int*a,int p,int q,int r){  //function to merge two arrays

int n1= (q-p); // size of first sub array
int n2= (r-q); // size of second subarray
int c[n1+1],d[n2]; //you need to add 1 otherwise you will lose out elements

for(int i=0;i<=n1;i++){
    c[i]=a[p+i];
    }

for(int j=0;j<n2;j++){
    d[j]=a[q+j+1];//This is to ensure that the second array starts after the mid element
    }

    int i=0,j=0;
int k;
for( k=p;k<=r;k++){ // merging two arrays in ascending order
    if( i<=n1 && j<n2 ){//you need to check the bounds else may get unexpected results
        if( c[i] <= d[j] )
            a[k] = c[i++];
        else
            a[k] = d[j++];
    }else if( i<=n1 ){
        a[k] = c[i++];
    }else{
        a[k] = d[j++];
    }
}
}



回答2:


First of all you should be correctly set for the size of the array.

void merge(int*a, int p, int q, int r) {  //function to merge two arrays
/* If i am not wrong , p is the starting index of the first sub array
   q is the ending index of it also q+1 is the starting index of second  
   sub array and r is the end of it */

/* size of the sub array would be (q-p+1) think about it*/
int n1 = (q - p);  // size of first sub array
/* This is right n2 = (r-(q+1)+1)*/
int n2 = (r - q);  // size of second subarray

int c[n1], d[n2];

for (int i = 0; i < n1; i++) {
c[i] = a[p + i];
}

for (int j = 0; j < n2; j++) {
d[j] = a[q + 1 + j];
}
.
.
.
}

Now , after this you have copies the both arrays in locally defined arrays. Until this, it is correct .

Now the main part is merging of the two arrays which you are doing in the for loop. You are just comparing the ith element of first sub array with jth element of the second, but what you are missing here is that there may be a time when you have updated all the values of the first( or second) sub array in the main array but still some elements are remaining int the second ( first) one.

For example, take these two subarrays

sub1={2,3,4,5};
sub2={7,8,9,10};

in this case you should break from the loop as soon as you have traversed either of the array completely and copy the rest of the elements of the other array in the same order. Also in the for loop you increasing k two times in a loop , one in the for statement and another while updating a value, Check that too. Hope this may solve the problem.



来源:https://stackoverflow.com/questions/30680576/what-is-wrong-in-this-implementation-of-merge-sort

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!