L-28 MCS 360 Wednesday 26 March 2003

Bubble Sort

1. the file bubble.h

/* L-28 prototype of bubble sort to sort any array of elements */

#define elements int

void bubble ( int n, elements a[n], int *np, int *nc, int *ns );
/* DESCRIPTION : applies bubble sort to sort the array;
 * ON ENTRY :
 *   n        number of elements to sort;
 *   a[n]     array of n elements to sort;
 * ON RETURN :
 *   a[n]     array sorted in ascending order;
 *   np       number of passes;
 *   nc       number of comparisons;
 *   ns       number of swaps.           */
The advantage of working with elements is that by only one small change in the header file, the definition for bubble will also work for short ints, floats, doubles, etc...

2. the file bubble.c

/* L-28 an implementation of bubble sort */

#include "bubble.h"

void bubble ( int n, elements a[n], int *np, int *nc, int *ns )
{
   int switched = 1;
   int i,tmp;

   *nc = 0; *ns = 0;
   for(*np = 0; ((*np < n-1) && (switched == 1)); (*np)++)
   {
      switched = 0;
      for(i=0; i < n-*np-1; i++, (*nc)++)
      {
         if(a[i] > a[i+1])
         {
            switched = 1;
            tmp = a[i];
            a[i] = a[i+1];
	    a[i+1] = tmp;
            (*ns)++;
         }
      }
   }
}

3. sorting random vectors

/* L-28 MCS 360 random tests on cost of bubble sort.
 *   The program below allows the user to specify a number of sorts
 * on randomly generated integer vectors.  With each sort we record
 * the number of passes, number of comparisons, and number of swaps.
 * In this way we obtain an experimental average case analysis. */

#define sort bubble

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"bubble.h"

void random_vector ( int n, int m, int a[n] );
/* returns n random integers modulo m in a */

void print_vector ( int n, int a[n] );
/* writes the vector to screen */

int main ( void )
{
   int i,s,m,N,sum_p,sum_c,sum_s;

   sum_p = 0; sum_c = 0; sum_s = 0;
   srand(time(NULL));

   printf("Give size of vectors to sort : ");
   scanf("%d", &s);
   printf("Give size of numbers in the vector : ");
   scanf("%d", &m);
   printf("Give total number of experiments : ");
   scanf("%d", &N);

   for(i=0; i<N; i++)
   {
      int a[s],np,nc,ns;
      random_vector(s,m,a);
      print_vector(s,a);
      sort(s,a,&np,&nc,&ns);
      print_vector(s,a);
      printf("  #passes = %d, #comparisons = %d, #swaps = %d\n",np,nc,ns);
      sum_p+=np; sum_c+=nc; sum_s+=ns;
   }
   printf("Sorted %d random vectors of size %d of numbers < %d\n",N,s,m);
   printf("  Average number of passes      : %d\n", sum_p/N);
   printf("  Average number of comparisons : %d\n", sum_c/N);
   printf("  Average number of swaps       : %d\n", sum_s/N);
      
   return 0;
}
void random_vector ( int n, int m, int a[n] )
{
   int i;
   for(i=0; i<n; i++) a[i] = rand() % m;
}

void print_vector ( int n, int a[n] )
{
   int i;
   for(i=0; i<n; i++) printf(" %d", a[i]);
   printf("\n");
}

4. Experimental Results

     n    #passes  #comparisons    #swaps
  ------------------------------------------
      10       7            41           21
     100      92         4,922        2,471
   1,000     958       498,461      247,907 
  10,000   9,798    49,971,849   24,799,837
We see clearly the O(n^2) effect: if we multiply the size n of our problem with 10, the amount of work (#comparisons and #swaps) multiplies with 100.

It was impossible for bubble sort to sort arrays with n = 100,000. For problems of this size, we need quick sort.

It is interesting to note that reducing the size of the numbers simulates the effect of the list to be nearly sorted and reduces the number of passes. In the extreme case, when the numbers are zeros and ones, the number of the passes tends to be one half of the size of the problem.

We introduced quick sort (more about this in next lecture). As a motivation, here are the data of the amount of work on the same type of random vectors:

     n  #partitions  #comparisons    #swaps
  ------------------------------------------
      10       6            28            8
     100      67           667          165
   1,000     900        12,955        2,379
  10,000   9,900       583,913       25,366
 100,000  99,900    50,867,705      255,561
Here the cost increases as O(n*log(n)).