qsort.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // qsort.c
  3. //
  4. // Quick sort
  5. //
  6. // Copyright (C) 2002 Michael Ringgaard. All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions
  10. // are met:
  11. //
  12. // 1. Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. // 2. Redistributions in binary form must reproduce the above copyright
  15. // notice, this list of conditions and the following disclaimer in the
  16. // documentation and/or other materials provided with the distribution.
  17. // 3. Neither the name of the project nor the names of its contributors
  18. // may be used to endorse or promote products derived from this software
  19. // without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  22. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  25. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. // SUCH DAMAGE.
  32. //
  33. #define CUTOFF 8
  34. static void shortsort(char *lo, char *hi, unsigned width, int (*comp)(const void *, const void *));
  35. static void swap(char *p, char *q, unsigned int width);
  36. __attribute__((used))
  37. void qsort(void *base, unsigned num, unsigned width, int (*comp)(const void *, const void *))
  38. {
  39. char *lo, *hi;
  40. char *mid;
  41. char *loguy, *higuy;
  42. unsigned size;
  43. char *lostk[30], *histk[30];
  44. int stkptr;
  45. if (num < 2 || width == 0) return;
  46. stkptr = 0;
  47. lo = base;
  48. hi = (char *) base + width * (num - 1);
  49. recurse:
  50. size = (hi - lo) / width + 1;
  51. if (size <= CUTOFF)
  52. {
  53. shortsort(lo, hi, width, comp);
  54. }
  55. else
  56. {
  57. mid = lo + (size / 2) * width;
  58. swap(mid, lo, width);
  59. loguy = lo;
  60. higuy = hi + width;
  61. for (;;)
  62. {
  63. do { loguy += width; } while (loguy <= hi && comp(loguy, lo) <= 0);
  64. do { higuy -= width; } while (higuy > lo && comp(higuy, lo) >= 0);
  65. if (higuy < loguy) break;
  66. swap(loguy, higuy, width);
  67. }
  68. swap(lo, higuy, width);
  69. if (higuy - 1 - lo >= hi - loguy)
  70. {
  71. if (lo + width < higuy)
  72. {
  73. lostk[stkptr] = lo;
  74. histk[stkptr] = higuy - width;
  75. ++stkptr;
  76. }
  77. if (loguy < hi)
  78. {
  79. lo = loguy;
  80. goto recurse;
  81. }
  82. }
  83. else
  84. {
  85. if (loguy < hi)
  86. {
  87. lostk[stkptr] = loguy;
  88. histk[stkptr] = hi;
  89. ++stkptr;
  90. }
  91. if (lo + width < higuy)
  92. {
  93. hi = higuy - width;
  94. goto recurse;
  95. }
  96. }
  97. }
  98. --stkptr;
  99. if (stkptr >= 0)
  100. {
  101. lo = lostk[stkptr];
  102. hi = histk[stkptr];
  103. goto recurse;
  104. }
  105. else
  106. return;
  107. }
  108. static void shortsort(char *lo, char *hi, unsigned width, int (*comp)(const void *, const void *))
  109. {
  110. char *p, *max;
  111. while (hi > lo)
  112. {
  113. max = lo;
  114. for (p = lo+width; p <= hi; p += width) if (comp(p, max) > 0) max = p;
  115. swap(max, hi, width);
  116. hi -= width;
  117. }
  118. }
  119. static void swap(char *a, char *b, unsigned width)
  120. {
  121. char tmp;
  122. if (a != b)
  123. {
  124. while (width--)
  125. {
  126. tmp = *a;
  127. *a++ = *b;
  128. *b++ = tmp;
  129. }
  130. }
  131. }