Search code examples
calgorithmsearchquicksortbubble-sort

Reading number of comparisons done by Search Algorithms


So I've been trying to write a random list sorting code with bubble and insertion sort in c; the intention of the code is to generate a random array, sort it with bubble sort then quicksort, then tell how many steps bubble sort took versus how many quicksort took. It then repeats this ten times and then finds the average number of steps that quicksort did and the average number of steps bubble sort did.

The issue I've encountered is that when I call for the number of steps that quicksort uses, I end up getting the number 1, and when I call for the average of the ten quicksorts, I get back 4950 (every time). I got it to work for bubble sort, but for some reason, it won't work for insertion sort - I think it has to do with optimizing my code to not being repetitive, but I don't know what to do next; any help would be greatly appreciated!

link to my code (to show output): https://onlinegdb.com/r14EPAGqm

My code:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

static int num_count_bubble_sort = 0;
static double avg_bubble = 0;
static int num_count_quick_sort = 0;
static double avg_quick = 0;

void swap(int *xp, int *yp) 
{ 
    int temp = *xp; 
    *xp = *yp; 
    *yp = temp; 
} 

// A function to implement bubble sort 
void bubbleSort(int arr[], int n) 
{ 
   int i, j;

   num_count_bubble_sort = 0;

   for (i = 0; i < n-1; i++)
   {
       int swapped = 0;

       // Last i elements are already in place 
       for (j = 0; j < n-i-1; j++)
       {
           num_count_bubble_sort++;
           avg_bubble++;

           if (arr[j] > arr[j+1])
           {
              swap(&arr[j], &arr[j+1]);
              swapped = 1;
           }
       }
      if (swapped == 0) break;
   }
} 

/* This function takes last element as pivot, places 
   the pivot element at its correct position in sorted 
   array, and places all smaller (smaller than pivot) 
   to left of pivot and all greater elements to right 
   of pivot */

int partition (int arr[], int low, int high) 
{ 
    int pivot = arr[high];    // pivot 
    int i = (low - 1);  // Index of smaller element 

    num_count_quick_sort =0;

    for (int j = low; j <= high- 1; j++) 
    { 
        // If current element is smaller than or 
        // equal to pivot

        num_count_quick_sort++;
        avg_quick++;

        if (arr[j] <= pivot) 
        { 
            i++;    // increment index of smaller element 
            swap(&arr[i], &arr[j]); 
        } 
    } 
    swap(&arr[i + 1], &arr[high]); 
    return (i + 1); 
} 

/* The main function that implements QuickSort 
 arr[] --> Array to be sorted, 
  low  --> Starting index, 
  high  --> Ending index */
void quickSort(int arr[], int low, int high) 
{ 
    if (low < high) 
    { 
        /* pi is partitioning index, arr[p] is now 
           at right place */
        int pi = partition(arr, low, high); 

        // Separately sort elements before 
        // partition and after partition 
        quickSort(arr, low, pi - 1); 
        quickSort(arr, pi + 1, high); 
    } 
} 

/* Function to print an array */
void printArray(int arr[], int size) 
{ 
    int i; 
    for (i=0; i < size; i++)
    {
        printf("%d ", arr[i]);
    }
} 

/* random array generator */
int main()
{
    srand(time(NULL));

    int l;

    for (int l = 10; l>0; l--)
    {
        int r;
        int arr[100];

        printf("Original Array: \n");

        for (int r = 99; r>=0; r--)
        {
            int rand_num = rand() % 100;

            printf("%d ",rand_num);

            arr[r] = rand_num;
        }

        /* bubble sort */

        int n = sizeof(arr)/sizeof(arr[0]); 

        bubbleSort(arr, n);

        printf("\n");

        printf("Bubble Sorted Array: \n"); 

        printArray(arr, n); 

        /*quick sort */
        num_count_quick_sort=0;
        quickSort(arr, 0, n-1);

        printf("\n");

        printf("Quick Sorted Array: \n");

        printArray(arr, n);

        printf("\n");

        /* printing amount of comparisons done by each sort */

        printf("comparisons done by bubble sort: %d ", 
num_count_bubble_sort);

        printf("\n");

        printf("comparisons done by Quick sort: %d ",num_count_quick_sort);

        printf("\n");
    }

    printf("\n");

    avg_quick = avg_quick/10.0;

    avg_bubble = avg_bubble/10.0;

    printf("average number of comparisons done by Bubble Sort (list length 
of 100 elements): %f", avg_bubble);

    printf("\n");

    printf("average number of comparisons done by Quick Sort(list length of 
100 elements): %f", avg_quick);
}

Just as a disclaimer, I just started learning c, so I will definitely not understand certain things about the language.


Solution

  • There are two things happening here.

    First, your test code does this:

    1. Create a randomized array
    2. Sort the array with bubble sort
    3. Sort the array with quick sort

    So you're always passing a sorted array to quick sort. That's why your average for quick sort is always equal to 4,950.

    To fix that problem, make a copy of the array and pass the copy to bubble sort. Then you're sure that quick sort and bubble sort are being supplied the same input.

    The reason num_count_quick_sort is always 1 is because you set it to 0 every time you enter the partition function. And since the last call to partition will always have high and low differ by 1, you'll only go through the iteration loop once. You need to remove that assignment in the partition function.

    One other thing is that your method for computing the average is a little odd, although in this case it produces the same result. What you're doing is accumulating a total for all runs at the same time you're accumulating the total for a single run. That is, you have:

    num_count_quick_sort++;
    avg_quick++;
    

    The more common way of doing this is to update avg_quick only at the end of a run. In your code you have:

        /* printing amount of comparisons done by each sort */
        printf("comparisons done by bubble sort: %d ", num_count_bubble_sort);
        printf("\n");
        printf("comparisons done by Quick sort: %d ,num_count_quick_sort);
        printf("\n");
    

    So you would remove the increment of avg_quick (and avg_bubble) from your loops, and instead write:

        /* printing amount of comparisons done by each sort */
        printf("comparisons done by bubble sort: %d\n", num_count_bubble_sort);
        avg_bubble += num_count_bubble_sort;
    
        printf("comparisons done by Quick sort: %d\n",num_count_quick_sort);
        avg_quick += num_count_quick_sort;
    

    (Note that I added a newline to the end of those printf statements. No need for a separate statement just to print a new line.)

    The primary reason for this isn't efficiency, but rather simplicity. It reduces the scope of the avg_quick and avg_bubble variables, making it easier to prevent them from being modified inadvertently by other, unrelated, code.