qsort.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * qsort -- simple quicksort
  3. */
  4. #include <u.h>
  5. typedef
  6. struct
  7. {
  8. int (*cmp)(void*, void*);
  9. void (*swap)(char*, char*, long);
  10. long es;
  11. } Sort;
  12. static void
  13. swapb(char *i, char *j, long es)
  14. {
  15. char c;
  16. do {
  17. c = *i;
  18. *i++ = *j;
  19. *j++ = c;
  20. es--;
  21. } while(es != 0);
  22. }
  23. static void
  24. swapi(char *ii, char *ij, long es)
  25. {
  26. long *i, *j, c;
  27. i = (long*)ii;
  28. j = (long*)ij;
  29. do {
  30. c = *i;
  31. *i++ = *j;
  32. *j++ = c;
  33. es -= sizeof(long);
  34. } while(es != 0);
  35. }
  36. static char*
  37. pivot(char *a, long n, Sort *p)
  38. {
  39. long j;
  40. char *pi, *pj, *pk;
  41. j = n/6 * p->es;
  42. pi = a + j; /* 1/6 */
  43. j += j;
  44. pj = pi + j; /* 1/2 */
  45. pk = pj + j; /* 5/6 */
  46. if(p->cmp(pi, pj) < 0) {
  47. if(p->cmp(pi, pk) < 0) {
  48. if(p->cmp(pj, pk) < 0)
  49. return pj;
  50. return pk;
  51. }
  52. return pi;
  53. }
  54. if(p->cmp(pj, pk) < 0) {
  55. if(p->cmp(pi, pk) < 0)
  56. return pi;
  57. return pk;
  58. }
  59. return pj;
  60. }
  61. static void
  62. qsorts(char *a, long n, Sort *p)
  63. {
  64. long j, es;
  65. char *pi, *pj, *pn;
  66. es = p->es;
  67. while(n > 1) {
  68. if(n > 10) {
  69. pi = pivot(a, n, p);
  70. } else
  71. pi = a + (n>>1)*es;
  72. p->swap(a, pi, es);
  73. pi = a;
  74. pn = a + n*es;
  75. pj = pn;
  76. for(;;) {
  77. do
  78. pi += es;
  79. while(pi < pn && p->cmp(pi, a) < 0);
  80. do
  81. pj -= es;
  82. while(pj > a && p->cmp(pj, a) > 0);
  83. if(pj < pi)
  84. break;
  85. p->swap(pi, pj, es);
  86. }
  87. p->swap(a, pj, es);
  88. j = (pj - a) / es;
  89. n = n-j-1;
  90. if(j >= n) {
  91. qsorts(a, j, p);
  92. a += (j+1)*es;
  93. } else {
  94. qsorts(a + (j+1)*es, n, p);
  95. n = j;
  96. }
  97. }
  98. }
  99. void
  100. qsort(void *va, long n, long es, int (*cmp)(void*, void*))
  101. {
  102. Sort s;
  103. s.cmp = cmp;
  104. s.es = es;
  105. s.swap = swapi;
  106. if(((uintptr)va | es) % sizeof(long))
  107. s.swap = swapb;
  108. qsorts((char*)va, n, &s);
  109. }