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