gsl_sort__sort.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Implement Heap sort -- direct and indirect sorting
  3. * Based on descriptions in Sedgewick "Algorithms in C"
  4. *
  5. * Copyright (C) 1999 Thomas Walter
  6. *
  7. * 18 February 2000: Modified for GSL by Brian Gough
  8. *
  9. * This is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by the
  11. * Free Software Foundation; either version 3, or (at your option) any
  12. * later version.
  13. *
  14. * This source is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  17. * for more details.
  18. */
  19. #include "gsl__config.h"
  20. #include <stdlib.h>
  21. #include "gsl_heapsort.h"
  22. static inline void swap (void *base, size_t size, size_t i, size_t j);
  23. static inline void downheap (void *data, const size_t size, const size_t N, size_t k, gsl_comparison_fn_t compare);
  24. /* Inline swap function for moving objects around */
  25. static inline void
  26. swap (void *base, size_t size, size_t i, size_t j)
  27. {
  28. register char *a = size * i + (char *) base;
  29. register char *b = size * j + (char *) base;
  30. register size_t s = size;
  31. if (i == j)
  32. return;
  33. do
  34. {
  35. char tmp = *a;
  36. *a++ = *b;
  37. *b++ = tmp;
  38. }
  39. while (--s > 0);
  40. }
  41. #define CMP(data,size,j,k) (compare((char *)(data) + (size) * (j), (char *)(data) + (size) * (k)))
  42. static inline void
  43. downheap (void *data, const size_t size, const size_t N, size_t k, gsl_comparison_fn_t compare)
  44. {
  45. while (k <= N / 2)
  46. {
  47. size_t j = 2 * k;
  48. if (j < N && CMP (data, size, j, j + 1) < 0)
  49. {
  50. j++;
  51. }
  52. if (CMP (data, size, k, j) < 0)
  53. {
  54. swap (data, size, j, k);
  55. }
  56. else
  57. {
  58. break;
  59. }
  60. k = j;
  61. }
  62. }
  63. void
  64. gsl_heapsort (void *data, size_t count, size_t size, gsl_comparison_fn_t compare)
  65. {
  66. /* Sort the array in ascending order. This is a true inplace
  67. algorithm with N log N operations. Worst case (an already sorted
  68. array) is something like 20% slower */
  69. size_t N;
  70. size_t k;
  71. if (count == 0)
  72. {
  73. return; /* No data to sort */
  74. }
  75. /* We have n_data elements, last element is at 'n_data-1', first at
  76. '0' Set N to the last element number. */
  77. N = count - 1;
  78. k = N / 2;
  79. k++; /* Compensate the first use of 'k--' */
  80. do
  81. {
  82. k--;
  83. downheap (data, size, N, k, compare);
  84. }
  85. while (k > 0);
  86. while (N > 0)
  87. {
  88. /* first swap the elements */
  89. swap (data, size, 0, N);
  90. /* then process the heap */
  91. N--;
  92. downheap (data, size, N, 0, compare);
  93. }
  94. }