mergesort.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright 2001, 2002 Adrian Thurston <thurston@cs.queensu.ca>
  3. */
  4. /* This file is part of Aapl.
  5. *
  6. * Aapl is free software; you can redistribute it and/or modify it under the
  7. * terms of the GNU Lesser General Public License as published by the Free
  8. * Software Foundation; either version 2.1 of the License, or (at your option)
  9. * any later version.
  10. *
  11. * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
  12. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
  18. * Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #ifndef _AAPL_MERGESORT_H
  21. #define _AAPL_MERGESORT_H
  22. #include "bubblesort.h"
  23. #ifdef AAPL_NAMESPACE
  24. namespace Aapl {
  25. #endif
  26. /**
  27. * \addtogroup sort
  28. * @{
  29. */
  30. /**
  31. * \class MergeSort
  32. * \brief Merge sort an array of data.
  33. *
  34. * MergeSort can be used to sort any array of objects of type T provided a
  35. * compare class is given. MergeSort is not in-place, it requires temporary
  36. * storage equal to the size of the array. The temporary storage is allocated
  37. * on the heap.
  38. *
  39. * Objects are not made aware that they are being moved around in memory.
  40. * Assignment operators, constructors and destructors are never invoked by the
  41. * sort.
  42. *
  43. * MergeSort runs in worst case O(n*log(n)) time. In most cases it is slower
  44. * than QuickSort because more copying is neccessary. But on the other hand,
  45. * it is a stable sort, meaning that objects with the same key have their
  46. * relative ordering preserved. Also, its worst case is better. MergeSort
  47. * switches to a BubbleSort when the size of the array being sorted is small.
  48. * This happens when directly sorting a small array or when MergeSort calls
  49. * itself recursively on a small portion of a larger array.
  50. */
  51. /*@}*/
  52. /* MergeSort. */
  53. template <class T, class Compare> class MergeSort
  54. : public BubbleSort<T, Compare>
  55. {
  56. public:
  57. /* Sorting interface routine. */
  58. void sort(T *data, long len);
  59. private:
  60. /* Recursive worker. */
  61. void doSort(T *tmpStor, T *data, long len);
  62. };
  63. #define _MS_BUBBLE_THRESH 16
  64. /* Recursive mergesort worker. Split data, make recursive calls, merge
  65. * results. */
  66. template< class T, class Compare> void MergeSort<T,Compare>::
  67. doSort(T *tmpStor, T *data, long len)
  68. {
  69. if ( len <= 1 )
  70. return;
  71. if ( len <= _MS_BUBBLE_THRESH ) {
  72. BubbleSort<T, Compare>::sort( data, len );
  73. return;
  74. }
  75. long mid = len / 2;
  76. doSort( tmpStor, data, mid );
  77. doSort( tmpStor + mid, data + mid, len - mid );
  78. /* Merge the data. */
  79. T *endLower = data + mid, *lower = data;
  80. T *endUpper = data + len, *upper = data + mid;
  81. T *dest = tmpStor;
  82. while ( true ) {
  83. if ( lower == endLower ) {
  84. /* Possibly upper left. */
  85. if ( upper != endUpper )
  86. memcpy( dest, upper, (endUpper - upper) * sizeof(T) );
  87. break;
  88. }
  89. else if ( upper == endUpper ) {
  90. /* Only lower left. */
  91. if ( lower != endLower )
  92. memcpy( dest, lower, (endLower - lower) * sizeof(T) );
  93. break;
  94. }
  95. else {
  96. /* Both upper and lower left. */
  97. if ( this->compare(*lower, *upper) <= 0 )
  98. memcpy( dest++, lower++, sizeof(T) );
  99. else
  100. memcpy( dest++, upper++, sizeof(T) );
  101. }
  102. }
  103. /* Copy back from the tmpStor array. */
  104. memcpy( data, tmpStor, sizeof( T ) * len );
  105. }
  106. /**
  107. * \brief Merge sort an array of data.
  108. */
  109. template< class T, class Compare>
  110. void MergeSort<T,Compare>::sort(T *data, long len)
  111. {
  112. /* Allocate the tmp space needed by merge sort, sort and free. */
  113. T *tmpStor = (T*) new char[sizeof(T) * len];
  114. doSort( tmpStor, data, len );
  115. delete[] (char*) tmpStor;
  116. }
  117. #ifdef AAPL_NAMESPACE
  118. }
  119. #endif
  120. #endif /* _AAPL_MERGESORT_H */