/* 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...
/* 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)++; } } } }
/* 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"); }
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,837We 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,561Here the cost increases as O(n*log(n)).