qsort.c 1.5 KB

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