You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

56 lines
1.6 KiB

  1. /*
  2. * This Quickselect routine is based on the algorithm described in
  3. * "Numerical recipes in C", Second Edition,
  4. * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
  5. * This code by Nicolas Devillard - 1998. Public domain.
  6. */
  7. #define ELEM_SWAP(a, b) { register float t = (a); (a) = (b); (b) = t; }
  8. float quick_select(float arr[], int n) {
  9. int low, median, high;
  10. int middle, ll, hh;
  11. low = 0; high = n-1; median = (low + high) / 2;
  12. for (;;) {
  13. if (high <= low) /* One element only */
  14. return arr[median] ;
  15. if (high == low + 1) { /* Two elements only */
  16. if (arr[low] > arr[high])
  17. ELEM_SWAP(arr[low], arr[high]);
  18. return arr[median];
  19. }
  20. /* Find median of low, middle and high items; swap into position low */
  21. middle = (low + high) / 2;
  22. if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]);
  23. if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]);
  24. if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]);
  25. /* Swap low item (now in position middle) into position (low+1) */
  26. ELEM_SWAP(arr[middle], arr[low+1]);
  27. /* Nibble from each end towards middle, swapping items when stuck */
  28. ll = low + 1;
  29. hh = high;
  30. for (;;) {
  31. do ll++; while (arr[low] > arr[ll]);
  32. do hh--; while (arr[hh] > arr[low]);
  33. if (hh < ll)
  34. break;
  35. ELEM_SWAP(arr[ll], arr[hh]);
  36. }
  37. /* Swap middle item (in position low) back into correct position */
  38. ELEM_SWAP(arr[low], arr[hh]);
  39. /* Re-set active partition */
  40. if (hh <= median)
  41. low = ll;
  42. if (hh >= median)
  43. high = hh - 1;
  44. }
  45. }
  46. #undef ELEM_SWAP