[net.sources] A Simple Bubble Sort Function

covert@ihuxq.UUCP (covert) (06/04/84)

< to the line eating wombat >

	I recently bought a book written by Jack Purdum, Tim Leslie, and
Alan Stegemoller titled "C Programmer's Library". This file contains a
version of the bubble sort function in their book with conforms to the
UNIX standard library. This version of bsort() is used in the same manner
as the ATT UNIX System V Release 2.0 version of qsort(3C). I have also
included a test program which can be used to test the bsort function,
or with minor changes the qsort function.
	
Remember to strip out the trailing lines of this message.

# to unbundle, csh this file
echo readme
cat >readme <<'End of readme'
		readme
		
	This documents the bubble sort function. The bubble sort function is
based upon the bubble sort function described in the book "C Programmer's
Library" written by Jack J. Purdum, Timothy C. Leslie, and Alan L.
Stegemoller; published by Que Corporation Indianapolis, Indiana 1984.

	The function as written conforms in usage with the qsort function 
available in the ATT UNIX System V Release 2.0 library.

Compile the file bsort.c:
cc -O -c bsort.c

Compile the file bsorttst.c
cc -O -o bsorttst bsorttst.c bsort.o

bsort.3c is the manual page for the bsort function.

	The reason that this function is different from the function in the
book is that the function required the data table to be global, and the
swap function to be written for each type of data to be sorted. This version
of bsort allows any simple, or aggregate, data type to be sorted. The user 
needs to write only the compare function used by bsort. The file bsorttst.c 
contains examples of three uses of the bsort function. One uses bsort to sort
integers, one for sorting doubles, and one for sorting a structure using the 
second field as the key. This same program can be used to test the qsort 
function simply by changing all calls to bsort() to calls to qsort().
'End of readme'
echo bsorttst.c
cat >bsorttst.c <<'End of bsorttst.c'
/* EMACS_MODES: tabstop=4, c, !save, !fill, !lnumb */
/* bubblesort.c	--A bubble sort routine. This is the based upon the
 *				bubble sort routine in the book "C Programmer's Library".
 *				I have rewritten it to confirm to the format of the qsort
 *				function in the UNIX System V Release 2.0 standard library.
 *
 * author: r.e.covert ihnp4!ihuxq!covert
 *
 * date: 6/4/84
 *
 * Original Source: 'C' Programmer's Library by Jack J. Purdum, 
 *					Timothy C. Leslie, Alan L. Stegemoller
 *					Published by Que Corporation Indianapolis Indiana 1984
 *
 * Usage:
 *		bsort(3)    
 *	void bsort(base, nel, sel, cmpr)
 *	char	*base;
 *	unsigned int	nel;
 *	unsigned int	sel;
 *	int		(*cmpr)();
 *
 */

/*************************************************************************
 *
 *	This program performs a bubble sort on 'n' records. It is independent
 *	of the record and key. This independence is possible because pointers
 *	to a key-comparison and record-swapping function are passed to the sort.
 *	The function convention is
 *
 *		bsort((char *) base, nel, sel, compar)
 *
 *	Where
 *
 *		base points to the element at the base of the table. base is of
 *			type pointer-to-element and is cast to pointer-to-char.
 *
 *		nel is the number of elements to sort.
 *
 *		sel is the size of each element.
 *
 *		compar is a pointer to a function that will compare two record keys
 *			and return an integer representing the logical relationship of
 *			the keys. Returns:
 *
 *			< 0		If key[i] < key[j] (ascending) or
 *					key[i] > key[j] (descending)
 *			= 0		If key[i] == key[j]
 *			> 0		If key[i] > key[j] (ascending) or
 *					key[i] < key[j] (descending)
 *
 *	compar is called with two paramters that are indices to
 *	records, with the record being 0 and the last record being n-1.
 *
 ************************************************************************/

/*************************************************************************
 *
 *	This proram illustrates the use of pointers to functions.
 *	In this program the pointers to functions are used to allow
 *	the sort algorithm to function independently of the date record.
 *
 ************************************************************************/

#ifndef void
#define void int
#endif
struct	form1 {
	int	a;
	int	b;
	float	c;
	char	d;
}

main()
{
	struct form1 *p;
	static struct form1 data1[] = {
		{ 73, 987, 123.456, 'a' },
		{ 54, 123, 876.77, 'b' },
		{ 123, 456, 34.0009, 'c' },
		{ 112, 023, 435.700, 'd' },
		{ 8, 1, 1.12, 'e'}
		};

	static int int_data[] = {
		12, 100, -9, -999, 1211, 12, 13, 0, 999, -1, 1 };
		   
	static double	dbl_data[] = {
		12.0, 100.0, -9.0, -999.0, 1211.0, 12.0, 13.0, 0.0, 999.0, -1.0, 1.0};

	int		nel, int_nel, dbl_nel, i , j;
	int		int_compar(), dbl_compar(),	struct_cmpr();
	extern int		bsort();
	
	int_nel = sizeof(int_data)/sizeof(int_data[0]);	
	printf("Integer table before sorting.\n");
	for (i = 0; i < int_nel; ++i) 
		printf(" %d", int_data[i]);
	printf("\nInteger table after sorting.\n");
	bsort( (char *)int_data, int_nel, sizeof(int_data[0]), int_compar);
	for (i = 0; i < int_nel; ++i) 
		printf(" %d", int_data[i]);
	printf("\n");
	printf("Double Data table before sorting.\n");
	dbl_nel = sizeof(dbl_data)/sizeof(dbl_data[0]);
	for (i = 0; i < dbl_nel; ++i) 
		printf(" %9.4f", dbl_data[i]);
	printf("\nDouble Data table after sorting.\n");
	bsort((char *) dbl_data, dbl_nel, sizeof(dbl_data[0]), dbl_compar);
	for (i = 0; i < dbl_nel; ++i) 
		printf(" %9.4f", dbl_data[i]);
	printf("\n");

	printf("\n\n\n");
	nel = sizeof(data1)/sizeof(data1[0]);
	
	printf("Complex structure before sorting.\n");
	for(p = data1, i = 0; i < nel; i++, p++) 
		printf("%5d %5d %9.4f %c\n", p->a, p->b, p->c, p->d);
	bsort(data1, nel, sizeof(data1[0]), struct_cmpr);
	printf("\n\n\n");
	printf("Complex structure after sorting.\n");
	for(p = data1, i = 0; i < nel; i++, p++) 
		printf("%5d %5d %9.4f %c\n", p->a, p->b, p->c, p->d);
}

int
int_compar(i, j)	/* integer comparison function */
int		*i, *j;		/* pointers to integer data */
{
	if (*i < *j )
		return(-1);
	else if (*i == *j)
		return(0);
	else
		return(1);
}

int
dbl_compar(i, j)	/* double comparison function */
double	*i,*j;		/* pointers to double data */
{
	if (*i < *j )
		return(-1);
	else if (*i == *j)
		return(0);
	else
		return(1);
}

int
struct_cmpr(p1, p2)
struct form1 *p1, *p2;
{
	int	ret = 0;
	
	if (p1->b < p2->b) 
		ret = -1;
	else if ( p1->b > p2->b)
		ret = 1;
	return(ret);
}
'End of bsorttst.c'
echo bsort.c
cat >bsort.c <<'End of bsort.c'
/* EMACS_MODES: tabstop=4, c, !save, !fill, !lnumb */
/* bubblesort.c	--A bubble sort routine. This is the based upon the
 *				bubble sort routine in the book "C Programmer's Library".
 *				I have rewritten it to confirm to the format of the qsort
 *				function in the UNIX System V Release 2.0 standard library.
 *
 * author: r.e.covert
 *
 * date: 6/4/84
 *
 * Original Source: 'C' Programmer's Library by Jack J. Purdum, 
 *					Timothy C. Leslie, Alan L. Stegemoller
 *					Published by Que Corporation Indianapolis Indiana 1984
 *
 * Usage:
 *		bsort(3)    
 *	void bsort(base, nel, sel, cmpr)
 *	char	*base;
 *	unsigned int	nel;
 *	unsigned int	sel;
 *	int		(*cmpr)();
 *
 */
 /************************************************************************
 *
 *	Bubble Sort
 *	As described by Knuth, p.107
 *
 ************************************************************************/

/*************************************************************************
 *
 *	This program performs a bubble sort on 'n' records. It is independent
 *	of the record and key. This independence is possible because pointers
 *	to a key-comparison and record-swapping function are passed to the sort.
 *	The function convention is
 *
 *		bsort((char *) base, nel, sel, compar)
 *
 *	Where
 *
 *		base points to the element at the base of the table. base is of
 *			type pointer-to-element and is cast to pointer-to-char.
 *
 *		nel is the number of elements to sort.
 *
 *		sel is the size of each element.
 *
 *		compar is a pointer to a function that will compare two record keys
 *			and return an integer representing the logical relationship of
 *			the keys. Returns:
 *
 *			< 0		If key[i] < key[j] (ascending) or
 *					key[i] > key[j] (descending)
 *			= 0		If key[i] == key[j]
 *			> 0		If key[i] > key[j] (ascending) or
 *					key[i] < key[j] (descending)
 *
 *	compar is called with two paramters that are indices to
 *	records, with the record being 0 and the last record being n-1.
 *
 ************************************************************************/

/*************************************************************************
 *
 *	This proram illustrates the use of pointers to functions.
 *	In this program the pointers to functions are used to allow
 *	the sort algorithm to function independently of the date record.
 *
 ************************************************************************/

#ifndef void
#define void int
#endif

/*	Bubble Sort Functions */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

void	
bsort(base, nel, sel, cmpr)	/* bubble sort function */
char		*base;			/* pointer to base of data table */
unsigned	nel;			/* Number of elements in the data table */
unsigned	sel;			/* The size of each element in the data table */
int			(*cmpr)();		/* A pointer to comparison function */
{
	unsigned	j;
	int		unsorted = FALSE;
	char	*ptr1, *ptr2;	/* pointers to elements in data table */
	void	bsexch();		/* exchange function for bsort() */
	int		ret;
	/* Psuedo-code :
	while not sorted {
		Assume table is sorted (set not sorted flag to false);
		set first pointer to bottom of table;
		set second pointer to first data item above first pointer;
		Verify that each item in the table is sorted by repeatedly
		searching the table for two adjacent items that are NOT
		sorted. If two adjacent items are not sorted then exchange them,
		set the not sorted flag TRUE, and continue searching the data table.
		If the not sorted flag is true when you reach the end of the table
		then start set the not sorted flag false, reset the data pointers to
		the bottom of the data table, and start searching the table again.
		Repeat this process until a complete pass through the table yields
		all items in sorted order.
	}
	*/
	do {
		unsorted = FALSE; /* break loop if unsorted == false */
		ptr1 = base;	/* set pointers to base of table */
		ptr2 = base + sel; /* & to base + 1 of table */
		for(j = 0; j < nel-1; ++j) { /* do not go past the end of the table */
			ret = (*cmpr)(ptr1, ptr2); /* perform the comparison */
			if ( ret > 0) { /* compare 2 pointers */
				bsexch(ptr1, ptr2, sel); /* exchange 2 pointers */
				unsorted = TRUE; /* continue to next pair of elements */
			}
			ptr1 += sel; ptr2 += sel;/* increment both pointers */
		}
	} while(unsorted); /* loop until entire table is sorted (nel*nel times) */
}

void
bsexch(i, j, n)
char	*i, *j;
int		n;
{
	register char	*ri, *rj, c;
	ri = i;
	rj = j;
	do {
		c = *ri;
		*ri++ = *rj;
		*rj++ = c;
	} while (--n);
}

/**************************** end of bsort functions  ********************/
'End of bsort.c'
echo bsort.3
cat >bsort.3 <<'End of bsort.3'
.TH BSORT 3 "UNSUPPORTED"
.SH NAME
bsort \- bubble sort
.SH SYNOPSIS
.B "void bsort ((char \(**) base, nel, sizeof (\(**base), compar)"
.br
.B unsigned int nel;
.br
.B int (\(**compar)( );
.SH DESCRIPTION
.I Bsort\^
is an implementation
of the bubble-sort algorithm.
It sorts a table of data in place.
.PP
.I Base\^
points to the element at the base of the table.
.I Nel\^
is the number of elements in the table.
.I Compar\^
is the name of the comparison function,
which is called with two arguments that point
to the elements being compared.
The function must return
an integer less than, equal to, or greater than zero
according as the first argument is to be considered
less than, equal to, or greater than the second.
.SH NOTES
The pointer to the base of the table should be
of type pointer-to-element,
and cast to type pointer-to-character.
.br
The comparison function need not compare every byte,
so arbitrary data may be contained in the elements in addition to the values
being compared.
.br
Although declared as type pointer-to-character,
the value returned should be cast into type pointer-to-element.
.SH SEE ALSO
sort(1), qsort(3C), bsearch(3C), lsearch(3C), string(3C).
'End of bsort.3'
-- 
			Richard Covert
			AT&T Bell Laboratories
			...ihnp4!ihuxq!covert
			(312) 979-7488
			

geoff@callan.UUCP (06/09/84)

Jack Purdum is rapidly getting a reputation as an idiot with me.  I thought
that by now *EVERYBODY* knew that the bubble sort is for cretins.  If you
want a quick simple sort, write a "selection sort":  search 0 thru n for the
largest item and swap it with the item in slot n;  repeat with n=n-1 until
done.  This is exactly the effect that the bubble sort achieves (think about
it for a while if you aren't sure), but without all the unnecessary exchanges.

Moral:	Don't waste your effort optimizing the wrong solution to the problem.

	Geoff Kuenning
	Callan Data Systems
	...!ihnp4!wlbr!callan!geoff

mas@ecsvax.UUCP (06/11/84)

Wirth states, " ... in fact, the Bubblesort has hardly anything to
recommend it except its catchy name. "
page 68 of Algorithms + Data Structures = Programs .

...decvax!mcnc!ecsvax!mas

gsp@ulysses.UUCP (Gary Perlman) (06/12/84)

> Jack Purdum is rapidly getting a reputation as an idiot with me.  I thought
> that by now *EVERYBODY* knew that the bubble sort is for cretins.  If you
> want a quick simple sort, write a "selection sort":  search 0 thru n for the
> largest item and swap it with the item in slot n;  repeat with n=n-1 until
> done.  This is exactly the effect that the bubble sort achieves (think about
> it for a while if you aren't sure), but without all the unnecessary exchanges.

> Moral:	Don't waste your effort optimizing the wrong solution to the problem.

> 	Geoff Kuenning
> 	Callan Data Systems
> 	...!ihnp4!wlbr!callan!geoff

It is true that bubble sort is about as bad an algorithm as can be found.
Floor sort, used by me when I once dropped my FORTAN deck, is a bit worse.
Still, bubble sort is useful as a teaching tool, and its impracticality
makes it unlikely that teachers can find implementations of it in C.
I have trouble finding serious fault with anyone generous enough to
post their software to net.sources.  I realized that I was free to ignore it.
So while I can't cheer for the posting of some code that people should not use
for efficiency's sake, I find personal attacks in very poor taste.

For another non-optimal sorting routine, see the standard C text,
The C Programming Language (Prentice Hall) for a shell sort routine.
For small arrays, it gives remarkably good results for such a small procedure.
	Gary Perlman	BTL MH 5D-105	(201) 582-3624	ulysses!gsp

mickey@proper.UUCP (06/13/84)

>> Wirth states, " ... in fact, the Bubblesort has hardly anything to
>> recommend it except its catchy name. "
>> page 68 of Algorithms + Data Structures = Programs .
>> 
>> ...decvax!mcnc!ecsvax!mas
>> 

That statement actually came from Knuth. See page 111 of Volume 3 from
"The Art of Computer Programming".

I read somewhere, though i am sorry i can't give a reference, that 
bubble sort is quite efficient for N <= 10  (where N is the number of
records to be sorted).

M. Thompson

ags@pucc-i (06/17/84)

>  I read somewhere, though i am sorry i can't give a reference, that 
>  bubble sort is quite efficient for N <= 10  (where N is the number of
>  records to be sorted).

You could also say that BASIC is quite efficient for N <= 10 (where N is
the number of lines in the program).
-- 

Dave Seaman			"My hovercraft is full of eels."
..!pur-ee!pucc-i:ags

nessus@mit-eddie.UUCP (Doug Alan) (06/18/84)

>	From: mickey@proper.UUCP

>	I read somewhere, though i am sorry i can't give a reference,
>	that bubble sort is quite efficient for N <= 10 (where N is the
>	number of records to be sorted).

The bubble sort is efficient for N <= 10, but the straight insertion
sort, which is easier to do, is more efficient.
-- 
				-Doug Alan
				 mit-eddie!nessus
				 Nessus@MIT-MC

				"What does 'I' mean"?