Search code examples
csortingmergesort

Weird output of merge sort for no. of entries not being a power of 2. - c


I have written a code for mergesort to sort an array of structures in c it works fine when i give no. of entries as a power of 2 but does not even sort the records for other no. of entries. I Would like to learn where is my logic going wrong??

Here is my code:

void Mergesort(struct record r[],int n)
{
    int k;
    if(n>1)
    {
        int i,j;
        struct record r1[n/2];
        struct record r2[n-n/2];
        for(i=0,j=n/2;i<n/2 && j<n;i++,j++)
        {
            r1[i]=r[i];
            r2[i]=r[j];
        }
        Mergesort(r1,n/2);
        Mergesort(r2,n/2);
        r=Merge(r1,r2,r,n);
    }

}

struct record * Merge(struct record r1[],struct record r2[],struct record r[],int n)
{
    int i=0,j=0,k=0;
    while(i<n/2 && j<n/2)
    {
        if (strcmp(r1[i].a,r2[j].a)<=0)
        {
            r[k]=r1[i];
            i=i+1;
        }
        else
        {
            r[k]=r2[j];
            j=j+1;
        }
        k=k+1;
    }
    if(i==n/2)
    {
        for(j;j<n/2 && k<n;j++,k++)
        {
            r[k]=r2[j];
        }

    }
    else
    {
        for(i;i<n/2 && k<n;i++,k++)
        {
            r[k]=r1[i];
        }
    }
    return r;
}

Any Help would be greatly appreciated.!!

Sample Input for 8 entries:

CS003 Vinay 10
CS005 Mouli 9.94
CS010 Gautham 9.94
CS020 Sneha 9.94
CS200 Mohit 9.93
CS012 Aarti 9.9
CS002 Adithya 9.78
CS001 Adithya 9.58

Getting correct output as follows:

CS012 Aarti 9.90
CS002 Adithya 9.78
CS001 Adithya 9.58
CS010 Gautham 9.94
CS200 Mohit 9.93
CS005 Mouli 9.94
CS020 Sneha 9.94
CS003 Vinay 10.00
**[Sorted according to the Names in the record]**

Sample input for 7 entries:

CS003 Vinay 10
CS005 Mouli 9.94
CS010 Gautham 9.94
CS020 Sneha 9.94
CS200 Mohit 9.93
CS012 Aarti 9.9
CS002 Adithya 9.78

Output(Weird):

CS200 Mohit 9.93
CS005 Mouli 9.94
CS020 Sneha 9.94
CS012 Aarti 9.90
CS003 Vinay 10.00
CS010 Gautham 9.94
CS002 Adithya 9.78

[Not at all sorted according to the names]

Solution

  • I would make the below changes:

    void Mergesort(struct record r[],int n)
    {
        int k;
        if(n>1)
        {
            int i,j;
            struct record r1[n/2];
            struct record r2[n-n/2];
            for(i=0; i<n/2; i++)
            {
                r1[i]=r[i];
            }
            for(i=0,j=n/2; j < n; i++,j++) // This is required because your previous logic used to skip the last element of j when n is odd.
            {
                r2[i]=r[j];
            }
            Mergesort(r1,n/2);
            Mergesort(r2,n-n/2);//this is 'n - n/2'
            r=Merge(r1,r2,r,n/2, n-n/2); //The sizes are different so pass both
        }
    
    }
    
    struct record * Merge(struct record r1[],struct record r2[],struct record r[],int r1N, int r2N)
    {
        int i=0,j=0,k=0;
        while(i<r1N && j<r2N)
        {
            if (strcmp(r1[i].a, r2[j].a)<=0)
            {
                r[k]=r1[i];
                i=i+1;
            }
            else
            {
                r[k]=r2[j];
                j=j+1;
            }
            k=k+1;
        }
        if(i==r1N)
        {
            for(j;j< r2N && k < (r1N + r2N);j++,k++)
            {
                r[k]=r2[j];
            }
    
        }
        else
        {
            for(i;i < r1N && k < (r1N+r2N); i++,k++)
            {
                r[k] = r1[i];
            }
        }
        return r;
    }