qsort.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:11k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* qsort.c - qsort file for stdlib  */
  2. /* Copyright 1992-1993 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01d,01jul93,jmm  fixed parameter order of quick_sort and insertion_sort (spr 2202)
  7. 01c,08feb93,jdi  documentation cleanup for 5.1.
  8. 01b,20sep92,smb  documentation additions.
  9. 01a,19jul92,smb  written and documented.
  10. */
  11. /*
  12. DESCRIPTION
  13.  * Copyright (c) 1980, 1983, 1990 The Regents of the University of California.
  14.  * All rights reserved.
  15.  *
  16.  * Redistribution and use in source and binary forms, with or without
  17.  * modification, are permitted provided that the following conditions
  18.  * are met:
  19.  * 1. Redistributions of source code must retain the above copyright
  20.  *    notice, this list of conditions and the following disclaimer.
  21.  * 2. Redistributions in binary form must reproduce the above copyright
  22.  *    notice, this list of conditions and the following disclaimer in the
  23.  *    documentation and/or other materials provided with the distribution.
  24.  * 3. All advertising materials mentioning features or use of this software
  25.  *    must display the following acknowledgement:
  26.  * This product includes software developed by the University of
  27.  * California, Berkeley and its contributors.
  28.  * 4. Neither the name of the University nor the names of its contributors
  29.  *    may be used to endorse or promote products derived from this software
  30.  *    without specific prior written permission.
  31.  *
  32.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  33.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  36.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  40.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  41.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  42.  * SUCH DAMAGE.
  43.  *
  44. INCLUDE FILES: stdlib.h
  45. SEE ALSO: American National Standard X3.159-1989
  46. NOMANUAL
  47. */
  48. #include "vxWorks.h"
  49. #include "stdlib.h"
  50. /*
  51.  * MTHRESH is the smallest partition for which we compare for a median
  52.  * value instead of using the middle value.
  53.  */
  54. #define MTHRESH 6
  55. /*
  56.  * THRESH is the minimum number of entries in a partition for continued
  57.  * partitioning.
  58.  */
  59. #define THRESH 4
  60. static void insertion_sort(), quick_sort(); 
  61. /*
  62.  * Swap two areas of size number of bytes.  Although qsort(3) permits random
  63.  * blocks of memory to be sorted, sorting pointers is almost certainly the
  64.  * common case (and, were it not, could easily be made so).  Regardless, it
  65.  * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
  66.  * arithmetic gets lost in the time required for comparison function calls.
  67.  */
  68. #define SWAP(a, b) 
  69.     {  
  70.     cnt = size; 
  71.     do 
  72.      ch = *a; 
  73.      *a++ = *b; 
  74.      *b++ = ch; 
  75.         } while (--cnt); 
  76.     }
  77. /*
  78.  * Knuth, Vol. 3, page 116, Algorithm Q, step b, argues that a single pass
  79.  * of straight insertion sort after partitioning is complete is better than
  80.  * sorting each small partition as it is created.  This isn't correct in this
  81.  * implementation because comparisons require at least one (and often two)
  82.  * function calls and are likely to be the dominating expense of the sort.
  83.  * Doing a final insertion sort does more comparisons than are necessary
  84.  * because it compares the "edges" and medians of the partitions which are
  85.  * known to be already sorted.
  86.  *
  87.  * This is also the reasoning behind selecting a small THRESH value (see
  88.  * Knuth, page 122, equation 26), since the quicksort algorithm does less
  89.  * comparisons than the insertion sort.
  90.  */
  91. #define SORT(bot, n) 
  92.     { 
  93.     if (n > 1) 
  94.      if (n == 2) 
  95.     { 
  96.          t1 = bot + size; 
  97.          if (compar (t1, bot) < 0) 
  98.           SWAP (t1, bot); 
  99.          } 
  100. else 
  101.          insertion_sort(bot, n, size, compar); 
  102.     }
  103. /******************************************************************************
  104. *
  105. * qsort - sort an array of objects (ANSI)
  106. *
  107. * This routine sorts an array of <nmemb> objects, the initial element of
  108. * which is pointed to by <bot>.  The size of each object is specified by
  109. * <size>.
  110. *
  111. * The contents of the array are sorted into ascending order according to a
  112. * comparison function pointed to by <compar>, which is called with two
  113. * arguments that point to the objects being compared.  The function shall
  114. * return an integer less than, equal to, or greater than zero if the first
  115. * argument is considered to be respectively less than, equal to, or greater
  116. * than the second.
  117. *
  118. * If two elements compare as equal, their order in the sorted array is
  119. * unspecified.
  120. *
  121. * INCLUDE FILES: stdlib.h
  122. *
  123. * RETURNS: N/A
  124. */
  125. void qsort
  126.     (
  127.     void * bot, /* initial element in array */
  128.     size_t nmemb, /* no. of objects in array */
  129.     size_t size, /* size of array element */
  130.     int (*compar) (const void *, const void *)  /* comparison function */
  131.     )
  132.     {
  133.     /* static void insertion_sort(), quick_sort(); */
  134.     if (nmemb <= 1)
  135.      return;
  136.     if (nmemb >= THRESH)
  137.      quick_sort (bot, nmemb, size, compar);
  138.     else
  139.      insertion_sort (bot, nmemb, size, compar);
  140.     }
  141. /******************************************************************************
  142. *
  143. * quick_sort - sort an array of objects.
  144. *
  145. * RETURNS: no value.
  146. * NOMANUAL
  147. */
  148. static void quick_sort
  149.     (
  150.     FAST char *  bot,
  151.     int          nmemb,
  152.     FAST int     size,
  153.     int          (*compar)()
  154.     )
  155.     {
  156.     FAST int    cnt;
  157.     FAST uint_t   ch;
  158.     FAST char *   top;
  159.     FAST char *   mid;
  160.     FAST char *   t1;
  161.     FAST char *   t2;
  162.     FAST int      n1;
  163.     FAST int      n2;
  164.     char *        bsv;
  165.     /* bot and nmemb must already be set. */
  166. partition:
  167.     /* find mid and top elements */
  168.     mid = bot + size * (nmemb >> 1);
  169.     top = bot + (nmemb - 1) * size;
  170.     /*
  171.      * Find the median of the first, last and middle element (see Knuth,
  172.      * Vol. 3, page 123, Eq. 28).  This test order gets the equalities
  173.      * right.
  174.      */
  175.     if (nmemb >= MTHRESH) 
  176. {
  177.      n1 = compar (bot, mid);
  178.      n2 = compar (mid, top);
  179.      if ((n1 < 0) && (n2 > 0))
  180.      t1 = compar (bot, top) < 0 ? top : bot;
  181.      else 
  182.     if ((n1 > 0) && (n2 < 0))
  183.      t1 = compar (bot, top) > 0 ? top : bot;
  184.      else
  185.      t1 = mid;
  186.         /* if mid element not selected, swap selection there */
  187.         if (t1 != mid) 
  188.             {
  189.             SWAP (t1, mid);
  190.             mid -= size;
  191.             }
  192.         }
  193.     /* Standard quicksort, Knuth, Vol. 3, page 116, Algorithm Q. */
  194. #define didswap n1
  195. #define newbot t1
  196. #define replace t2
  197.     didswap = 0;
  198.     bsv = bot;
  199.     FOREVER
  200. {
  201.      while ((bot < mid) && (compar (bot, mid) <= 0))
  202.     {
  203.     bot += size;
  204.     }
  205.      while (top > mid) 
  206.     {
  207.          if (compar (mid, top) <= 0) 
  208. {
  209.           top -= size;
  210.           continue;
  211.              }
  212.          newbot = bot + size; /* value of bot after swap */
  213.          if (bot == mid) /* top <-> mid, mid == top */
  214.           replace = mid = top;
  215.          else 
  216. { /* bot <-> top */
  217.           replace = top;
  218.           top -= size;
  219.              }
  220.          goto swap;
  221.          }
  222.      if (bot == mid)
  223.      break;
  224.      /* bot <-> mid, mid == bot */
  225.      replace = mid;
  226.      newbot = mid = bot; /* value of bot after swap */
  227.      top -= size;
  228. swap: SWAP(bot, replace);
  229.      bot = newbot;
  230.      didswap = 1;
  231.         }
  232.     /*
  233.      * Quicksort behaves badly in the presence of data which is already
  234.      * sorted (see Knuth, Vol. 3, page 119) going from O N lg N to O N^2.
  235.      * To avoid this worst case behavior, if a re-partitioning occurs
  236.      * without swapping any elements, it is not further partitioned and
  237.      * is insert sorted.  This wins big with almost sorted data sets and
  238.      * only loses if the data set is very strangely partitioned.  A fix
  239.      * for those data sets would be to return prematurely if the insertion
  240.      * sort routine is forced to make an excessive number of swaps, and
  241.      * continue the partitioning.
  242.      */
  243.     if (!didswap) 
  244. {
  245.      insertion_sort (bsv, nmemb, size, compar);
  246.      return;
  247.         }
  248.     /*
  249.      * Re-partition or sort as necessary.  Note that the mid element
  250.      * itself is correctly positioned and can be ignored.
  251.      */
  252. #define nlower n1
  253. #define nupper n2
  254.     bot = bsv;
  255.     nlower = (mid - bot) / size; /* size of lower partition */
  256.     mid += size;
  257.     nupper = nmemb - nlower - 1; /* size of upper partition */
  258.     /*
  259.      * If must call recursively, do it on the smaller partition; this
  260.      * bounds the stack to lg N entries.
  261.      */
  262.     if (nlower > nupper) 
  263. {
  264.      if (nupper >= THRESH)
  265.          quick_sort (mid, nupper, size, compar);
  266.      else 
  267.     {
  268.          SORT (mid, nupper);
  269.          if (nlower < THRESH) 
  270. {
  271.           SORT (bot, nlower);
  272.           return;
  273.              }
  274.          }
  275.      nmemb = nlower;
  276.         } 
  277.     else 
  278. {
  279.      if (nlower >= THRESH)
  280.          quick_sort (bot, nlower, size, compar);
  281.      else 
  282.     {
  283.          SORT (bot, nlower);
  284.          if (nupper < THRESH) 
  285. {
  286.      SORT (mid, nupper);
  287.      return;
  288.      }
  289.          }
  290.      bot = mid;
  291.      nmemb = nupper;
  292.         }
  293.     goto partition;
  294.     /* NOTREACHED */
  295.     }
  296. /******************************************************************************
  297. *
  298. * insertion_sort - internal routine
  299. *
  300. * RETURNS: no value.
  301. * NOMANUAL
  302. */
  303. static void insertion_sort
  304.     (
  305.     char *       bot,
  306.     int          nmemb,
  307.     FAST int     size,
  308.     int          (*compar)()
  309.     )
  310.     {
  311.     FAST int     cnt;
  312.     FAST uint_t  ch;
  313.     FAST char *  s1;
  314.     FAST char *  s2;
  315.     FAST char *  t1;
  316.     FAST char *  t2;
  317.     FAST char *  top;
  318.     /*
  319.      * A simple insertion sort (see Knuth, Vol. 3, page 81, Algorithm
  320.      * S).  Insertion sort has the same worst case as most simple sorts
  321.      * (O N^2).  It gets used here because it is (O N) in the case of
  322.      * sorted data.
  323.      */
  324.     top = bot + nmemb * size;
  325.     for (t1 = bot + size; t1 < top;) 
  326. {
  327.      for (t2 = t1; ((t2 -= size) >= bot) && (compar (t1, t2) < 0);)
  328.     ;
  329.      if (t1 != (t2 += size)) 
  330.     {
  331.          /* Bubble bytes up through each element. */
  332.          for (cnt = size; cnt--; ++t1) 
  333. {
  334.           ch = *t1;
  335.           for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2)
  336.     {
  337.               *s1 = *s2;
  338.     }
  339.           *s1 = ch;
  340.              }
  341.          } 
  342.         else
  343.          t1 += size;
  344.         }
  345.     }