xref: /csrg-svn/lib/libc/stdlib/qsort.c (revision 46599)
142126Sbostic /*-
245643Sbostic  * Copyright (c) 1980, 1983, 1990 The Regents of the University of California.
334434Sbostic  * All rights reserved.
434434Sbostic  *
542126Sbostic  * %sccs.include.redist.c%
622102Smckusick  */
71975Swnj 
826577Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*46599Sdonn static char sccsid[] = "@(#)qsort.c	5.9 (Berkeley) 02/23/91";
1034434Sbostic #endif /* LIBC_SCCS and not lint */
1122102Smckusick 
1245643Sbostic #include <sys/types.h>
13*46599Sdonn #include <stdlib.h>
1442179Sbostic 
1511449Smckusick /*
1645643Sbostic  * MTHRESH is the smallest partition for which we compare for a median
1745643Sbostic  * value instead of using the middle value.
1811449Smckusick  */
1945643Sbostic #define	MTHRESH	6
201975Swnj 
2145643Sbostic /*
2245643Sbostic  * THRESH is the minimum number of entries in a partition for continued
2345643Sbostic  * partitioning.
2445643Sbostic  */
2545643Sbostic #define	THRESH	4
261975Swnj 
2745643Sbostic void
2845643Sbostic qsort(bot, nmemb, size, compar)
29*46599Sdonn 	void *bot;
30*46599Sdonn 	size_t nmemb, size;
31*46599Sdonn 	int (*compar) __P((const void *, const void *));
3245643Sbostic {
33*46599Sdonn 	static void insertion_sort(), quick_sort();
341975Swnj 
3545643Sbostic 	if (nmemb <= 1)
3645643Sbostic 		return;
3745643Sbostic 
3845643Sbostic 	if (nmemb >= THRESH)
3945643Sbostic 		quick_sort(bot, nmemb, size, compar);
4045643Sbostic 	else
4145643Sbostic 		insertion_sort(bot, nmemb, size, compar);
4245643Sbostic }
4345643Sbostic 
4411449Smckusick /*
4545643Sbostic  * Swap two areas of size number of bytes.  Although qsort(3) permits random
4645643Sbostic  * blocks of memory to be sorted, sorting pointers is almost certainly the
4745643Sbostic  * common case (and, were it not, could easily be made so).  Regardless, it
4845643Sbostic  * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
4945643Sbostic  * arithmetic gets lost in the time required for comparison function calls.
5011449Smckusick  */
5145643Sbostic #define	SWAP(a, b) { \
5245643Sbostic 	cnt = size; \
5345643Sbostic 	do { \
5445643Sbostic 		ch = *a; \
5545643Sbostic 		*a++ = *b; \
5645643Sbostic 		*b++ = ch; \
5745643Sbostic 	} while (--cnt); \
5845643Sbostic }
591975Swnj 
6045643Sbostic /*
6145643Sbostic  * Knuth, Vol. 3, page 116, Algorithm Q, step b, argues that a single pass
6245643Sbostic  * of straight insertion sort after partitioning is complete is better than
6345643Sbostic  * sorting each small partition as it is created.  This isn't correct in this
6445643Sbostic  * implementation because comparisons require at least one (and often two)
6545643Sbostic  * function calls and are likely to be the dominating expense of the sort.
6645643Sbostic  * Doing a final insertion sort does more comparisons than are necessary
6745643Sbostic  * because it compares the "edges" and medians of the partitions which are
6845643Sbostic  * known to be already sorted.
6945643Sbostic  *
7045643Sbostic  * This is also the reasoning behind selecting a small THRESH value (see
7145643Sbostic  * Knuth, page 122, equation 26), since the quicksort algorithm does less
7245643Sbostic  * comparisons than the insertion sort.
7345643Sbostic  */
7445643Sbostic #define	SORT(bot, n) { \
7545643Sbostic 	if (n > 1) \
7645643Sbostic 		if (n == 2) { \
7745643Sbostic 			t1 = bot + size; \
7845643Sbostic 			if (compar(t1, bot) < 0) \
7945643Sbostic 				SWAP(t1, bot); \
8045643Sbostic 		} else \
8145643Sbostic 			insertion_sort(bot, n, size, compar); \
8245643Sbostic }
8345643Sbostic 
8445643Sbostic static void
8545643Sbostic quick_sort(bot, nmemb, size, compar)
8645643Sbostic 	register char *bot;
8745643Sbostic 	register int size;
8845643Sbostic 	int nmemb, (*compar)();
8911449Smckusick {
9045643Sbostic 	register int cnt;
9145643Sbostic 	register u_char ch;
9245643Sbostic 	register char *top, *mid, *t1, *t2;
9345643Sbostic 	register int n1, n2;
9445643Sbostic 	char *bsv;
95*46599Sdonn 	static void insertion_sort();
961975Swnj 
9745643Sbostic 	/* bot and nmemb must already be set. */
9845643Sbostic partition:
9945643Sbostic 
10045643Sbostic 	/* find mid and top elements */
10145643Sbostic 	mid = bot + size * (nmemb >> 1);
10245643Sbostic 	top = bot + (nmemb - 1) * size;
10345643Sbostic 
10411449Smckusick 	/*
10545643Sbostic 	 * Find the median of the first, last and middle element (see Knuth,
10645643Sbostic 	 * Vol. 3, page 123, Eq. 28).  This test order gets the equalities
10745643Sbostic 	 * right.
10811449Smckusick 	 */
10945643Sbostic 	if (nmemb >= MTHRESH) {
11045643Sbostic 		n1 = compar(bot, mid);
11145643Sbostic 		n2 = compar(mid, top);
11245643Sbostic 		if (n1 < 0 && n2 > 0)
11345643Sbostic 			t1 = compar(bot, top) < 0 ? top : bot;
11445643Sbostic 		else if (n1 > 0 && n2 < 0)
11545643Sbostic 			t1 = compar(bot, top) > 0 ? top : bot;
11645643Sbostic 		else
11745643Sbostic 			t1 = mid;
11845643Sbostic 
11945643Sbostic 		/* if mid element not selected, swap selection there */
12045643Sbostic 		if (t1 != mid) {
12145643Sbostic 			SWAP(t1, mid);
12245643Sbostic 			mid -= size;
12311449Smckusick 		}
12411449Smckusick 	}
12545643Sbostic 
12645643Sbostic 	/* Standard quicksort, Knuth, Vol. 3, page 116, Algorithm Q. */
12745643Sbostic #define	didswap	n1
12845643Sbostic #define	newbot	t1
12945643Sbostic #define	replace	t2
13045643Sbostic 	didswap = 0;
13145643Sbostic 	for (bsv = bot;;) {
13245643Sbostic 		for (; bot < mid && compar(bot, mid) <= 0; bot += size);
13345643Sbostic 		while (top > mid) {
13445643Sbostic 			if (compar(mid, top) <= 0) {
13545643Sbostic 				top -= size;
13645643Sbostic 				continue;
1371975Swnj 			}
13845643Sbostic 			newbot = bot + size;	/* value of bot after swap */
13945643Sbostic 			if (bot == mid)		/* top <-> mid, mid == top */
14045643Sbostic 				replace = mid = top;
14145643Sbostic 			else {			/* bot <-> top */
14245643Sbostic 				replace = top;
14345643Sbostic 				top -= size;
14445643Sbostic 			}
14545643Sbostic 			goto swap;
1461975Swnj 		}
14745643Sbostic 		if (bot == mid)
14845643Sbostic 			break;
14945643Sbostic 
15045643Sbostic 		/* bot <-> mid, mid == bot */
15145643Sbostic 		replace = mid;
15245643Sbostic 		newbot = mid = bot;		/* value of bot after swap */
15345643Sbostic 		top -= size;
15445643Sbostic 
15545643Sbostic swap:		SWAP(bot, replace);
15645643Sbostic 		bot = newbot;
15745643Sbostic 		didswap = 1;
15811449Smckusick 	}
1591975Swnj 
16045643Sbostic 	/*
16145643Sbostic 	 * Quicksort behaves badly in the presence of data which is already
16245643Sbostic 	 * sorted (see Knuth, Vol. 3, page 119) going from O N lg N to O N^2.
16345643Sbostic 	 * To avoid this worst case behavior, if a re-partitioning occurs
16445643Sbostic 	 * without swapping any elements, it is not further partitioned and
16545643Sbostic 	 * is insert sorted.  This wins big with almost sorted data sets and
16645643Sbostic 	 * only loses if the data set is very strangely partitioned.  A fix
16745643Sbostic 	 * for those data sets would be to return prematurely if the insertion
16845643Sbostic 	 * sort routine is forced to make an excessive number of swaps, and
16945643Sbostic 	 * continue the partitioning.
17045643Sbostic 	 */
17145643Sbostic 	if (!didswap) {
17245643Sbostic 		insertion_sort(bsv, nmemb, size, compar);
17345643Sbostic 		return;
17445643Sbostic 	}
17511449Smckusick 
17645643Sbostic 	/*
17745643Sbostic 	 * Re-partition or sort as necessary.  Note that the mid element
17845643Sbostic 	 * itself is correctly positioned and can be ignored.
17945643Sbostic 	 */
18045643Sbostic #define	nlower	n1
18145643Sbostic #define	nupper	n2
18245643Sbostic 	bot = bsv;
18345643Sbostic 	nlower = (mid - bot) / size;	/* size of lower partition */
18445643Sbostic 	mid += size;
18545643Sbostic 	nupper = nmemb - nlower - 1;	/* size of upper partition */
18611449Smckusick 
18711449Smckusick 	/*
18845643Sbostic 	 * If must call recursively, do it on the smaller partition; this
18945643Sbostic 	 * bounds the stack to lg N entries.
19011449Smckusick 	 */
19145643Sbostic 	if (nlower > nupper) {
19245643Sbostic 		if (nupper >= THRESH)
19345643Sbostic 			quick_sort(mid, nupper, size, compar);
19445643Sbostic 		else {
19545643Sbostic 			SORT(mid, nupper);
19645643Sbostic 			if (nlower < THRESH) {
19745643Sbostic 				SORT(bot, nlower);
19845643Sbostic 				return;
1991975Swnj 			}
20011449Smckusick 		}
20145643Sbostic 		nmemb = nlower;
20245643Sbostic 	} else {
20345643Sbostic 		if (nlower >= THRESH)
20445643Sbostic 			quick_sort(bot, nlower, size, compar);
20545643Sbostic 		else {
20645643Sbostic 			SORT(bot, nlower);
20745643Sbostic 			if (nupper < THRESH) {
20845643Sbostic 				SORT(mid, nupper);
20945643Sbostic 				return;
2101975Swnj 			}
2111975Swnj 		}
21245643Sbostic 		bot = mid;
21345643Sbostic 		nmemb = nupper;
21445643Sbostic 	}
21545643Sbostic 	goto partition;
21645643Sbostic 	/* NOTREACHED */
2171975Swnj }
21845643Sbostic 
21945643Sbostic static void
22045643Sbostic insertion_sort(bot, nmemb, size, compar)
22145643Sbostic 	char *bot;
22245643Sbostic 	register int size;
22345643Sbostic 	int nmemb, (*compar)();
22445643Sbostic {
22545643Sbostic 	register int cnt;
22645643Sbostic 	register u_char ch;
22745643Sbostic 	register char *s1, *s2, *t1, *t2, *top;
22845643Sbostic 
22945643Sbostic 	/*
23045643Sbostic 	 * A simple insertion sort (see Knuth, Vol. 3, page 81, Algorithm
23145643Sbostic 	 * S).  Insertion sort has the same worst case as most simple sorts
23245643Sbostic 	 * (O N^2).  It gets used here because it is (O N) in the case of
23345643Sbostic 	 * sorted data.
23445643Sbostic 	 */
23545643Sbostic 	top = bot + nmemb * size;
23645643Sbostic 	for (t1 = bot + size; t1 < top;) {
23745643Sbostic 		for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;);
23845643Sbostic 		if (t1 != (t2 += size)) {
23945643Sbostic 			/* Bubble bytes up through each element. */
24045643Sbostic 			for (cnt = size; cnt--; ++t1) {
24145643Sbostic 				ch = *t1;
24245643Sbostic 				for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2)
24345643Sbostic 					*s1 = *s2;
24445643Sbostic 				*s1 = ch;
24545643Sbostic 			}
24645643Sbostic 		} else
24745643Sbostic 			t1 += size;
24845643Sbostic 	}
24945643Sbostic }
250