ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

qsort.c
Go to the documentation of this file.
00001 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
00002 
00003 #include <stdlib.h>
00004 #include <search.h>
00005 
00006 /*-
00007  * Copyright (c) 1980, 1983 The Regents of the University of California.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms are permitted
00011  * provided that: (1) source distributions retain this entire copyright
00012  * notice and comment, and (2) distributions including binaries display
00013  * the following acknowledgement:  ``This product includes software
00014  * developed by the University of California, Berkeley and its contributors''
00015  * in the documentation or other materials provided with the distribution
00016  * and in all advertising materials mentioning features or use of this
00017  * software. Neither the name of the University nor the names of its
00018  * contributors may be used to endorse or promote products derived
00019  * from this software without specific prior written permission.
00020  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
00021  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00023  */
00024 
00025 /*
00026  * qsort.c:
00027  * Our own version of the system qsort routine which is faster by an average
00028  * of 25%, with lows and highs of 10% and 50%.
00029  * The THRESHold below is the insertion sort threshold, and has been adjusted
00030  * for records of size 48 bytes.
00031  * The MTHREShold is where we stop finding a better median.
00032  */
00033 
00034 #define     THRESH      4       /* threshold for insertion */
00035 #define     MTHRESH     6       /* threshold for median */
00036 
00037 /*
00038  * qst:
00039  * Do a quicksort
00040  * First, find the median element, and put that one in the first place as the
00041  * discriminator.  (This "median" is just the median of the first, last and
00042  * middle elements).  (Using this median instead of the first element is a big
00043  * win).  Then, the usual partitioning/swapping, followed by moving the
00044  * discriminator into the right place.  Then, figure out the sizes of the two
00045  * partions, do the smaller one recursively and the larger one via a repeat of
00046  * this code.  Stopping when there are less than THRESH elements in a partition
00047  * and cleaning up with an insertion sort (in our caller) is a huge win.
00048  * All data swaps are done in-line, which is space-losing but time-saving.
00049  * (And there are only three places where this is done).
00050  */
00051 
00052 static void
00053 qst(size_t size, int (__cdecl *compar)(const void*, const void*), char *base, char *max)
00054 {
00055   char c, *i, *j, *jj;
00056   size_t ii;
00057   char *mid, *tmp;
00058   size_t lo, hi;
00059   size_t thresh;
00060   size_t mthresh;
00061 
00062   thresh = size * THRESH;
00063   mthresh = size * MTHRESH;
00064 
00065   /*
00066    * At the top here, lo is the number of characters of elements in the
00067    * current partition.  (Which should be max - base).
00068    * Find the median of the first, last, and middle element and make
00069    * that the middle element.  Set j to largest of first and middle.
00070    * If max is larger than that guy, then it's that guy, else compare
00071    * max with loser of first and take larger.  Things are set up to
00072    * prefer the middle, then the first in case of ties.
00073    */
00074   lo = max - base;      /* number of elements as chars */
00075   do    {
00076     mid = i = base + size * ((lo / size) >> 1);
00077     if (lo >= mthresh)
00078     {
00079       j = (compar((jj = base), i) > 0 ? jj : i);
00080       if (compar(j, (tmp = max - size)) > 0)
00081       {
00082     /* switch to first loser */
00083     j = (j == jj ? i : jj);
00084     if (compar(j, tmp) < 0)
00085       j = tmp;
00086       }
00087       if (j != i)
00088       {
00089     ii = size;
00090     do  {
00091       c = *i;
00092       *i++ = *j;
00093       *j++ = c;
00094     } while (--ii);
00095       }
00096     }
00097     /*
00098      * Semi-standard quicksort partitioning/swapping
00099      */
00100     for (i = base, j = max - size; ; )
00101     {
00102       while (i < mid && compar(i, mid) <= 0)
00103     i += size;
00104       while (j > mid)
00105       {
00106     if (compar(mid, j) <= 0)
00107     {
00108       j -= size;
00109       continue;
00110     }
00111     tmp = i + size; /* value of i after swap */
00112     if (i == mid)
00113     {
00114       /* j <-> mid, new mid is j */
00115       mid = jj = j;
00116     }
00117     else
00118     {
00119       /* i <-> j */
00120       jj = j;
00121       j -= size;
00122     }
00123     goto swap;
00124       }
00125       if (i == mid)
00126       {
00127     break;
00128       }
00129       else
00130       {
00131     /* i <-> mid, new mid is i */
00132     jj = mid;
00133     tmp = mid = i;      /* value of i after swap */
00134     j -= size;
00135       }
00136     swap:
00137       ii = size;
00138       do    {
00139     c = *i;
00140     *i++ = *jj;
00141     *jj++ = c;
00142       } while (--ii);
00143       i = tmp;
00144     }
00145     /*
00146      * Look at sizes of the two partitions, do the smaller
00147      * one first by recursion, then do the larger one by
00148      * making sure lo is its size, base and max are update
00149      * correctly, and branching back.  But only repeat
00150      * (recursively or by branching) if the partition is
00151      * of at least size THRESH.
00152      */
00153     i = (j = mid) + size;
00154     if ((lo = j - base) <= (hi = max - i))
00155     {
00156       if (lo >= thresh)
00157     qst(size, compar, base, j);
00158       base = i;
00159       lo = hi;
00160     }
00161     else
00162     {
00163       if (hi >= thresh)
00164     qst(size, compar, i, max);
00165       max = j;
00166     }
00167   } while (lo >= thresh);
00168 }
00169 
00170 /*
00171  * qsort:
00172  * First, set up some global parameters for qst to share.  Then, quicksort
00173  * with qst(), and then a cleanup insertion sort ourselves.  Sound simple?
00174  * It's not...
00175  *
00176  * @implemented
00177  */
00178 void
00179 qsort(void *base0, size_t n, size_t size, int (__cdecl *compar)(const void*, const void*))
00180 {
00181   char *base = (char *)base0;
00182   char c, *i, *j, *lo, *hi;
00183   char *min, *max;
00184   size_t thresh;
00185 
00186   if (n <= 1)
00187     return;
00188 
00189   if (size == 0)
00190     return;
00191   compar = compar;
00192   thresh = size * THRESH;
00193   max = base + n * size;
00194   if (n >= THRESH)
00195   {
00196     qst(size, compar, base, max);
00197     hi = base + thresh;
00198   }
00199   else
00200   {
00201     hi = max;
00202   }
00203   /*
00204    * First put smallest element, which must be in the first THRESH, in
00205    * the first position as a sentinel.  This is done just by searching
00206    * the first THRESH elements (or the first n if n < THRESH), finding
00207    * the min, and swapping it into the first position.
00208    */
00209   for (j = lo = base; (lo += size) < hi; )
00210     if (compar(j, lo) > 0)
00211       j = lo;
00212   if (j != base)
00213   {
00214     /* swap j into place */
00215     for (i = base, hi = base + size; i < hi; )
00216     {
00217       c = *j;
00218       *j++ = *i;
00219       *i++ = c;
00220     }
00221   }
00222   /*
00223    * With our sentinel in place, we now run the following hyper-fast
00224    * insertion sort.  For each remaining element, min, from [1] to [n-1],
00225    * set hi to the index of the element AFTER which this one goes.
00226    * Then, do the standard insertion sort shift on a character at a time
00227    * basis for each element in the frob.
00228    */
00229   for (min = base; (hi = min += size) < max; )
00230   {
00231     while (compar(hi -= size, min) > 0)
00232       /* void */;
00233     if ((hi += size) != min) {
00234       for (lo = min + size; --lo >= min; )
00235       {
00236     c = *lo;
00237     for (i = j = lo; (j -= size) >= hi; i = j)
00238       *i = *j;
00239     *i = c;
00240       }
00241     }
00242   }
00243 }

Generated on Sat May 26 2012 04:35:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.