Search code examples
calgorithmsortingmergesortarray-merge

Error in implementing bubble sorting in a merge sort program in C


I am learning data structure and algorithms. The program takes a set number of inputs in an array and sorts them out using merge sort. The condition is whenever the size of a sub-array is equal to or smaller than 10, it should sort the elements out using bubble sort and then merge them together. My problem is with getting the program to bubble sort. So far I have been unable to find out the mistake in my program. I am still learning everyday. I would really appreciate it if someone could help me find the error and fix it please. Thank you very much and have a g'day.

Here's the code:

#include<stdio.h>
#include<stdlib.h>
#define arrsize 10
void merge_sort(int, int);
void merge_array(int, int, int, int);
int arr_sort[arrsize];
void bubblesort(int a[],int size);
void main()
{
  int a[50],n,i;
   printf("\nEnter %d Elements for Sorting\n", arrsize);
  for (i = 0; i < arrsize; i++)
    scanf("%d", &arr_sort[i]);

  printf("\nYour Data   :");
  for (i = 0; i < arrsize; i++) {
    printf("\t%d", arr_sort[i]);
  }

  merge_sort(0, arrsize - 1);

  printf("\n\nSorted Data :");
  for (i = 0; i < arrsize; i++) {
    printf("\t%d", arr_sort[i]);
  }

}
void bubblesort(int arr_sort[],int size)
{
  int temp,i,j;
  for(i=0;i<size;i++)
  {
   for(j=0;j<size-1;j++)
   {
    if(arr_sort[j]>arr_sort[j+1])
    {
     temp=arr_sort[j];
     arr_sort[j]=arr_sort[j+1];
     arr_sort[j+1]=temp;
    }
  }
 }
}
void merge_sort(int i, int j) {
  int m;
  if (i < j) {
    m = (i + j) / 2;
       if(m<=5)
    {
        for(i=0;i<=m;i++){
            for(j=i+1;j<=m;j++){
        bubblesort(arr_sort[i],m);
        bubblesort(arr_sort[j],m);}}
        merge_array(i,m,m+1,j);
    }
    else
         merge_sort(i, m);
    merge_sort(m + 1, j);
    merge_array(i, m, m + 1, j);
  }
}

void merge_array(int a, int b, int c, int d) {
  int t[50];
  int i = a, j = c, k = 0;

  while (i <= b && j <= d) {
    if (arr_sort[i] < arr_sort[j])
      t[k++] = arr_sort[i++];
    else
      t[k++] = arr_sort[j++];
  }
  while (i <= b)
    t[k++] = arr_sort[i++];

  while (j <= d)
    t[k++] = arr_sort[j++];

  for (i = a, j = 0; i <= d; i++, j++)
    arr_sort[i] = t[j];
}

Solution

  • Among the issues in your code:

    1. From merge_sort, you should be calling bubble_sort for a given floor magnitude, hard-fixed in your merge_sort, specified globally, or as an argument to your functions. The former of these is easiest to achieve.

    2. Your bubble_sort invocation from merge_sort is wrong from inception, as you're passing int values where int* should be present.

    3. Your functions should all take the array to sort as an argument, and at least the length as well. This makes the functions more robust, and thanks to pointer arithmetic, easier to implement than you may think.

    Fixing this requires major surgery.

    Updated merge_array

    First some surgery for the merge_array function. This assumes you support variable length arrays (VLAs). Notice the function accepts the array base address, the mid point, and the overall length.

    void merge_array(int a[], int mid, int len)
    {
        // change to int tmp[arrsize], or use dynamic allocation, if your
        // platform doesn't support VLAs
        int tmp[len];
    
        int i = 0, j = mid, k = 0;
        while (i < mid && j < len)
            tmp[k++] = ((a[i] < a[j]) ? a[i++] : a[j++]);
    
        while (i < mid)
            tmp[k++] = a[i++];
    
        for (i = 0; i < k; ++i)
            a[i] = tmp[i];
    }
    

    Updated merge_sort

    Now the merge_sort function as described in the problem analysis. Like the above, it should take an array base address and a length, but that's all it needs. Pointer arithmetic will let us partition on recursed calls.

    void merge_sort(int a[], int len)
    {
        if (len < 5)
        {
            // bubblesort short partitions (less than length:5)
            bubble_sort(a, len);
        }
        else
        {
            int mid = len / 2;
            merge_sort(a, mid);
            merge_sort(a + mid, len - mid); // note pointer arithmetic here
            merge_array(a, mid, len);
        }
    }
    

    Updated bubble_sort

    This simple bubble sort uses forward swap detection to leave early on already-sorted detection. Like the prior functions, we have the base address of some array and a specified length.

    void bubble_sort(int a[], int size)
    {
        int swapped = 1;
        while (swapped && size-- > 0)
        {
            swapped = 0;
            for (int i = 0; i < size; ++i)
            {
                if (a[i + 1] < a[i])
                {
                    int tmp = a[i];
                    a[i] = a[i + 1];
                    a[i + 1] = tmp;
                    swapped = 1;
                }
            }
        }
    }
    

    Putting It All Together

    Below is the complete program, which includes a print helper to dump an array to the console, and a random-generator to avoid lengthy keyboard input. The provided main() creates a random-filled array, prints it, sorts it, then prints the result. Obviously the output will vary with each run, but you hopefully get the idea of how the above functions are called.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define arrsize 40
    
    void merge_sort(int a[], int len);
    void merge_array(int a[], int mid, int len);
    void bubble_sort(int a[], int size);
    
    void merge_array(int a[], int mid, int len)
    {
        // change to int tmp[arrsize], or use dynamic allocation, if your
        // platform doesn't support VLAs
        int tmp[len];
    
        int i = 0, j = mid, k = 0;
        while (i < mid && j < len)
            tmp[k++] = ((a[i] < a[j]) ? a[i++] : a[j++]);
    
        while (i < mid)
            tmp[k++] = a[i++];
    
        for (i = 0; i < k; ++i)
            a[i] = tmp[i];
    }
    
    void merge_sort(int a[], int len)
    {
        if (len < 5)
        {
            // bubblesort short partitions (less than length:5)
            bubble_sort(a, len);
        }
        else
        {
            int mid = len / 2;
            merge_sort(a, mid);
            merge_sort(a + mid, len - mid); // note pointer arithmetic here
            merge_array(a, mid, len);
        }
    }
    
    void bubble_sort(int a[], int size)
    {
        int swapped = 1;
        while (swapped && size-- > 0)
        {
            swapped = 0;
            for (int i = 0; i < size; ++i)
            {
                if (a[i + 1] < a[i])
                {
                    int tmp = a[i];
                    a[i] = a[i + 1];
                    a[i + 1] = tmp;
                    swapped = 1;
                }
            }
        }
    }
    
    void print_arr(int const arr[], int len)
    {
        while (len-- > 0)
            printf("%d ", *arr++);
        fputc('\n', stdout);
    }
    
    int main()
    {
        srand((unsigned)time(NULL));
    
        int arr_sort[arrsize];
    
        // generate random array
        for (int i = 0; i < arrsize; ++i)
            arr_sort[i] = 1 + rand() % 99;
        print_arr(arr_sort, arrsize);
    
        // sort the array
        merge_sort(arr_sort, arrsize);
        print_arr(arr_sort, arrsize);
    }
    

    Sample Output

    16 81 73 86 87 66 14 93 19 13 62 32 70 56 29 88 20 21 7 27 70 46 72 42 95 83 24 2 5 43 67 79 8 18 82 39 81 56 56 45
    2 5 7 8 13 14 16 18 19 20 21 24 27 29 32 39 42 43 45 46 56 56 56 62 66 67 70 70 72 73 79 81 81 82 83 86 87 88 93 95
    

    Hope it helps.