简体   繁体   中英

3-way Merge Sort C program

I have trying to "upgrade" my normal merge sort for a school project. But my new code seems to not coorporate as it should

so i have a MergeSort3way function that splits the Array inputed in 3 subArrays then it call itself till the sort is finished but the outputs are far from right.

void Mergesort3way(int A[],int n){
//Sort array A with divition of 3
int B[n/3];
int C[n/3];
int D[n/3];
int i,c;

if(n>1){
    for(i=0;i<n/3;i++){
        B[i]=A[i];
    }
    for(i=n/3;i<2*n/3;i++){
        c= i-n/3;
        C[c]=A[i];
    }
    for(i=2*n/3;i<n;i++){
        c=i-(2*n/3);
        D[c]=A[i];
    }

Mergesort3way(B,n/3);
Mergesort3way(C,n/3);
Mergesort3way(D,n/3);
int bn = sizeof(B)/sizeof(B[0]);
int cn = sizeof(C)/sizeof(C[0]);
int dn = sizeof(D)/sizeof(D[0]);
Merge3way(B,C,D,A,bn,cn,dn);    
}

}

After that the merge3way combines them into 1 sigle sorted array

void Merge3way(int B[],int C[],int D[],int A[],int p,int q,int r){
int i=0,j=0,u=0,k=0;

while(i<p && j<q && u<r){
    if(B[i]<C[j]){
        if(B[i]<D[u]){
            A[k]=D[u];
            u++;
        }else{
            A[k]=B[i];
            i++;
        }
    }else{
        if(C[j]<D[u]){
          A[k]=D[u];
          u++;  
        }else{
          A[k]=C[j];
          j++;
        }
    }
    k++;
 }
int all = p+q+r;    
if(i==p){
    if(u==r){
     while(j<q && k<all){
        A[k]=C[j];
        k++;
        j++;            
     } 
    }else{
        while(u<r && k<all){
        A[k]=D[u];
        k++;
        u++;
        }
    }
}else if(j==q){
    if(u==r){
     while(i<p && k<all){
        A[k]=B[i];
        k++;
        i++;            
     } 
}
  }
} 

Can you suggest me any solution so i can sort as it should i've been trying over 2 hours of moding it and the result are always the same. Thanks in advance please no hard feeling as it is my first time using the site.

If this is supposed to be an ascending sort, then if (B[i] < C[j]) && (B[i] < D[u]), the code should do A[k] = B[i].

Once the end of B[], C[], or D[] is reached the code needs to switch to a 2 way merge on the remaining two. You can swap array names (which are effectively pointers in a called function), to simplify this, so the 2 way merge uses B and C. If the end of B is reached first, then B = C and C = D. If the end of C is reached first, then C = D. If the end of D is reached first, then no array (pointer) assignments are needed.

Once the end of B or C is reached, then just copy the remaining sub-array.

For consistent naming on the indices, I would have used k for D[], and u for A[], but this isn't causing a problem.

I think this part of your code,

while(i<p && j<q && u<r){
    if(B[i]<C[j]){
        if(B[i]<D[u]){
            A[k]=D[u];
            u++;
        }else{
            A[k]=B[i];
            i++;
        }
    }else{
        if(C[j]<D[u]){
          A[k]=D[u];
          u++;  
        }else{
          A[k]=C[j];
          j++;
        }
    }
    k++;
 }

needs to change to this:

while(i<p && j<q && u<r){
    if(B[i]<C[j]){
        if(B[i]<D[u]){
            A[k]=B[i];
            i++;
        }else{
            A[k]=D[u];
            u++;
        }
    }else{
        if(C[j]<D[u]){
          A[k]=C[j];
          j++;  
        }else{
          A[k]=D[u];
          u++;
        }
    }
    k++;
 }

And this portion of your code:

if(i==p){
    if(u==r){
     while(j<q && k<all){
        A[k]=C[j];
        k++;
        j++;            
     } 
    }else{
        while(u<r && k<all){
        A[k]=D[u];
        k++;
        u++;
        }
    }
}else if(j==q){
    if(u==r){
     while(i<p && k<all){
        A[k]=B[i];
        k++;

needs to change to something like this:

if (i < p && j < q){
  # append the result of normal merge of remaining elements of B and C to A
} else if (j < q && u < r) {
  # append the result of normal merge of remaining elements of C and D to A
} else if (i < p && u < r) {
  # append the result of normal merge of remaining elements of B and D to A
} else {
      if (i == p && j == q && u < r){
         # append remaining elements of D to A
      } else if (i < p && j == q && u == r){
         # append remaining elements of B to A
      } else if (i == p && j < q && u == r){
         # append remaining elements of C to A
      }
}

Although, as you said that you had a normal mergesort which you are trying to modify, well, how about if after sorting every 1/3 rd portion of the array, like this:

Mergesort3way(B,n/3);
Mergesort3way(C,n/3);
Mergesort3way(D,n/3);

you combine any of the two sorted portions first using normal mergesort , and then combine the result of both of them with the third portion again using normal mergesort . For example: first merge sorted B with sorted C using normal mergesort , let's call their result BmC , then merge their result BmC with sorted D using normal mergesort , leading us to final merge result: BmCmD .

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