142126Sbostic /*- 2*45643Sbostic * 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*45643Sbostic static char sccsid[] = "@(#)qsort.c 5.8 (Berkeley) 11/26/90"; 1034434Sbostic #endif /* LIBC_SCCS and not lint */ 1122102Smckusick 12*45643Sbostic #include <sys/types.h> 1342179Sbostic 1411449Smckusick /* 15*45643Sbostic * MTHRESH is the smallest partition for which we compare for a median 16*45643Sbostic * value instead of using the middle value. 1711449Smckusick */ 18*45643Sbostic #define MTHRESH 6 191975Swnj 20*45643Sbostic /* 21*45643Sbostic * THRESH is the minimum number of entries in a partition for continued 22*45643Sbostic * partitioning. 23*45643Sbostic */ 24*45643Sbostic #define THRESH 4 251975Swnj 26*45643Sbostic void 27*45643Sbostic qsort(bot, nmemb, size, compar) 28*45643Sbostic char *bot; 29*45643Sbostic int nmemb, size, (*compar)(); 30*45643Sbostic { 31*45643Sbostic void insertion_sort(), quick_sort(); 321975Swnj 33*45643Sbostic if (nmemb <= 1) 34*45643Sbostic return; 35*45643Sbostic 36*45643Sbostic if (nmemb >= THRESH) 37*45643Sbostic quick_sort(bot, nmemb, size, compar); 38*45643Sbostic else 39*45643Sbostic insertion_sort(bot, nmemb, size, compar); 40*45643Sbostic } 41*45643Sbostic 4211449Smckusick /* 43*45643Sbostic * Swap two areas of size number of bytes. Although qsort(3) permits random 44*45643Sbostic * blocks of memory to be sorted, sorting pointers is almost certainly the 45*45643Sbostic * common case (and, were it not, could easily be made so). Regardless, it 46*45643Sbostic * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer 47*45643Sbostic * arithmetic gets lost in the time required for comparison function calls. 4811449Smckusick */ 49*45643Sbostic #define SWAP(a, b) { \ 50*45643Sbostic cnt = size; \ 51*45643Sbostic do { \ 52*45643Sbostic ch = *a; \ 53*45643Sbostic *a++ = *b; \ 54*45643Sbostic *b++ = ch; \ 55*45643Sbostic } while (--cnt); \ 56*45643Sbostic } 571975Swnj 58*45643Sbostic /* 59*45643Sbostic * Knuth, Vol. 3, page 116, Algorithm Q, step b, argues that a single pass 60*45643Sbostic * of straight insertion sort after partitioning is complete is better than 61*45643Sbostic * sorting each small partition as it is created. This isn't correct in this 62*45643Sbostic * implementation because comparisons require at least one (and often two) 63*45643Sbostic * function calls and are likely to be the dominating expense of the sort. 64*45643Sbostic * Doing a final insertion sort does more comparisons than are necessary 65*45643Sbostic * because it compares the "edges" and medians of the partitions which are 66*45643Sbostic * known to be already sorted. 67*45643Sbostic * 68*45643Sbostic * This is also the reasoning behind selecting a small THRESH value (see 69*45643Sbostic * Knuth, page 122, equation 26), since the quicksort algorithm does less 70*45643Sbostic * comparisons than the insertion sort. 71*45643Sbostic */ 72*45643Sbostic #define SORT(bot, n) { \ 73*45643Sbostic if (n > 1) \ 74*45643Sbostic if (n == 2) { \ 75*45643Sbostic t1 = bot + size; \ 76*45643Sbostic if (compar(t1, bot) < 0) \ 77*45643Sbostic SWAP(t1, bot); \ 78*45643Sbostic } else \ 79*45643Sbostic insertion_sort(bot, n, size, compar); \ 80*45643Sbostic } 81*45643Sbostic 82*45643Sbostic static void 83*45643Sbostic quick_sort(bot, nmemb, size, compar) 84*45643Sbostic register char *bot; 85*45643Sbostic register int size; 86*45643Sbostic int nmemb, (*compar)(); 8711449Smckusick { 88*45643Sbostic register int cnt; 89*45643Sbostic register u_char ch; 90*45643Sbostic register char *top, *mid, *t1, *t2; 91*45643Sbostic register int n1, n2; 92*45643Sbostic char *bsv; 931975Swnj 94*45643Sbostic /* bot and nmemb must already be set. */ 95*45643Sbostic partition: 96*45643Sbostic 97*45643Sbostic /* find mid and top elements */ 98*45643Sbostic mid = bot + size * (nmemb >> 1); 99*45643Sbostic top = bot + (nmemb - 1) * size; 100*45643Sbostic 10111449Smckusick /* 102*45643Sbostic * Find the median of the first, last and middle element (see Knuth, 103*45643Sbostic * Vol. 3, page 123, Eq. 28). This test order gets the equalities 104*45643Sbostic * right. 10511449Smckusick */ 106*45643Sbostic if (nmemb >= MTHRESH) { 107*45643Sbostic n1 = compar(bot, mid); 108*45643Sbostic n2 = compar(mid, top); 109*45643Sbostic if (n1 < 0 && n2 > 0) 110*45643Sbostic t1 = compar(bot, top) < 0 ? top : bot; 111*45643Sbostic else if (n1 > 0 && n2 < 0) 112*45643Sbostic t1 = compar(bot, top) > 0 ? top : bot; 113*45643Sbostic else 114*45643Sbostic t1 = mid; 115*45643Sbostic 116*45643Sbostic /* if mid element not selected, swap selection there */ 117*45643Sbostic if (t1 != mid) { 118*45643Sbostic SWAP(t1, mid); 119*45643Sbostic mid -= size; 12011449Smckusick } 12111449Smckusick } 122*45643Sbostic 123*45643Sbostic /* Standard quicksort, Knuth, Vol. 3, page 116, Algorithm Q. */ 124*45643Sbostic #define didswap n1 125*45643Sbostic #define newbot t1 126*45643Sbostic #define replace t2 127*45643Sbostic didswap = 0; 128*45643Sbostic for (bsv = bot;;) { 129*45643Sbostic for (; bot < mid && compar(bot, mid) <= 0; bot += size); 130*45643Sbostic while (top > mid) { 131*45643Sbostic if (compar(mid, top) <= 0) { 132*45643Sbostic top -= size; 133*45643Sbostic continue; 1341975Swnj } 135*45643Sbostic newbot = bot + size; /* value of bot after swap */ 136*45643Sbostic if (bot == mid) /* top <-> mid, mid == top */ 137*45643Sbostic replace = mid = top; 138*45643Sbostic else { /* bot <-> top */ 139*45643Sbostic replace = top; 140*45643Sbostic top -= size; 141*45643Sbostic } 142*45643Sbostic goto swap; 1431975Swnj } 144*45643Sbostic if (bot == mid) 145*45643Sbostic break; 146*45643Sbostic 147*45643Sbostic /* bot <-> mid, mid == bot */ 148*45643Sbostic replace = mid; 149*45643Sbostic newbot = mid = bot; /* value of bot after swap */ 150*45643Sbostic top -= size; 151*45643Sbostic 152*45643Sbostic swap: SWAP(bot, replace); 153*45643Sbostic bot = newbot; 154*45643Sbostic didswap = 1; 15511449Smckusick } 1561975Swnj 157*45643Sbostic /* 158*45643Sbostic * Quicksort behaves badly in the presence of data which is already 159*45643Sbostic * sorted (see Knuth, Vol. 3, page 119) going from O N lg N to O N^2. 160*45643Sbostic * To avoid this worst case behavior, if a re-partitioning occurs 161*45643Sbostic * without swapping any elements, it is not further partitioned and 162*45643Sbostic * is insert sorted. This wins big with almost sorted data sets and 163*45643Sbostic * only loses if the data set is very strangely partitioned. A fix 164*45643Sbostic * for those data sets would be to return prematurely if the insertion 165*45643Sbostic * sort routine is forced to make an excessive number of swaps, and 166*45643Sbostic * continue the partitioning. 167*45643Sbostic */ 168*45643Sbostic if (!didswap) { 169*45643Sbostic insertion_sort(bsv, nmemb, size, compar); 170*45643Sbostic return; 171*45643Sbostic } 17211449Smckusick 173*45643Sbostic /* 174*45643Sbostic * Re-partition or sort as necessary. Note that the mid element 175*45643Sbostic * itself is correctly positioned and can be ignored. 176*45643Sbostic */ 177*45643Sbostic #define nlower n1 178*45643Sbostic #define nupper n2 179*45643Sbostic bot = bsv; 180*45643Sbostic nlower = (mid - bot) / size; /* size of lower partition */ 181*45643Sbostic mid += size; 182*45643Sbostic nupper = nmemb - nlower - 1; /* size of upper partition */ 18311449Smckusick 18411449Smckusick /* 185*45643Sbostic * If must call recursively, do it on the smaller partition; this 186*45643Sbostic * bounds the stack to lg N entries. 18711449Smckusick */ 188*45643Sbostic if (nlower > nupper) { 189*45643Sbostic if (nupper >= THRESH) 190*45643Sbostic quick_sort(mid, nupper, size, compar); 191*45643Sbostic else { 192*45643Sbostic SORT(mid, nupper); 193*45643Sbostic if (nlower < THRESH) { 194*45643Sbostic SORT(bot, nlower); 195*45643Sbostic return; 1961975Swnj } 19711449Smckusick } 198*45643Sbostic nmemb = nlower; 199*45643Sbostic } else { 200*45643Sbostic if (nlower >= THRESH) 201*45643Sbostic quick_sort(bot, nlower, size, compar); 202*45643Sbostic else { 203*45643Sbostic SORT(bot, nlower); 204*45643Sbostic if (nupper < THRESH) { 205*45643Sbostic SORT(mid, nupper); 206*45643Sbostic return; 2071975Swnj } 2081975Swnj } 209*45643Sbostic bot = mid; 210*45643Sbostic nmemb = nupper; 211*45643Sbostic } 212*45643Sbostic goto partition; 213*45643Sbostic /* NOTREACHED */ 2141975Swnj } 215*45643Sbostic 216*45643Sbostic static void 217*45643Sbostic insertion_sort(bot, nmemb, size, compar) 218*45643Sbostic char *bot; 219*45643Sbostic register int size; 220*45643Sbostic int nmemb, (*compar)(); 221*45643Sbostic { 222*45643Sbostic register int cnt; 223*45643Sbostic register u_char ch; 224*45643Sbostic register char *s1, *s2, *t1, *t2, *top; 225*45643Sbostic 226*45643Sbostic /* 227*45643Sbostic * A simple insertion sort (see Knuth, Vol. 3, page 81, Algorithm 228*45643Sbostic * S). Insertion sort has the same worst case as most simple sorts 229*45643Sbostic * (O N^2). It gets used here because it is (O N) in the case of 230*45643Sbostic * sorted data. 231*45643Sbostic */ 232*45643Sbostic top = bot + nmemb * size; 233*45643Sbostic for (t1 = bot + size; t1 < top;) { 234*45643Sbostic for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;); 235*45643Sbostic if (t1 != (t2 += size)) { 236*45643Sbostic /* Bubble bytes up through each element. */ 237*45643Sbostic for (cnt = size; cnt--; ++t1) { 238*45643Sbostic ch = *t1; 239*45643Sbostic for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2) 240*45643Sbostic *s1 = *s2; 241*45643Sbostic *s1 = ch; 242*45643Sbostic } 243*45643Sbostic } else 244*45643Sbostic t1 += size; 245*45643Sbostic } 246*45643Sbostic } 247