qsort.c 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. #include <sys/types.h>
  2. #include <stdlib.h>
  3. static void exch(char* base,size_t size,size_t a,size_t b) {
  4. char* x=base+a*size;
  5. char* y=base+b*size;
  6. while (size) {
  7. char z=*x;
  8. *x=*y;
  9. *y=z;
  10. --size; ++x; ++y;
  11. }
  12. }
  13. /* Quicksort with 3-way partitioning, ala Sedgewick */
  14. /* Blame him for the scary variable names */
  15. /* http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf */
  16. static void quicksort(char* base,size_t size,ssize_t l,ssize_t r,
  17. int (*compar)(const void*,const void*)) {
  18. ssize_t i=l-1, j=r, p=l-1, q=r, k;
  19. char* v=base+r*size;
  20. if (r<=l) return;
  21. for (;;) {
  22. while (++i != r && compar(base+i*size,v)<0) ;
  23. while (compar(v,base+(--j)*size)<0) if (j == l) break;
  24. if (i >= j) break;
  25. exch(base,size,i,j);
  26. if (compar(base+i*size,v)==0) exch(base,size,++p,i);
  27. if (compar(v,base+j*size)==0) exch(base,size,j,--q);
  28. }
  29. exch(base,size,i,r); j = i-1; ++i;
  30. for (k=l; k<p; k++, j--) exch(base,size,k,j);
  31. for (k=r-1; k>q; k--, i++) exch(base,size,i,k);
  32. quicksort(base,size,l,j,compar);
  33. quicksort(base,size,i,r,compar);
  34. }
  35. void qsort(void* base,size_t nmemb,size_t size,int (*compar)(const void*,const void*)) {
  36. /* check for integer overflows */
  37. if (nmemb >= (((size_t)-1)>>1) ||
  38. size >= (((size_t)-1)>>1)) return;
  39. if (nmemb>1)
  40. quicksort(base,size,0,nmemb-1,compar);
  41. }