merge.hxx
Go to the documentation of this file.
1 /*===========================================================================================================
2  *
3  * HUC - Hurna Core
4  *
5  * Copyright (c) Michael Jeulin-Lagarrigue
6  *
7  * Licensed under the MIT License, you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * https://github.com/Hurna/Hurna-Core/blob/master/LICENSE
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License is
13  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and limitations under the License.
15  *
16  * The above copyright notice and this permission notice shall be included in all copies or
17  * substantial portions of the Software.
18  *
19  *=========================================================================================================*/
20 #ifndef MODULE_SORT_MERGE_HXX
21 #define MODULE_SORT_MERGE_HXX
22 
23 // STD includes
24 #include <iterator>
25 
26 namespace huc
27 {
28  namespace sort
29  {
46  template <typename IT, typename Compare = std::less<typename std::iterator_traits<IT>::value_type>>
48  {
49  public:
50  void operator()(const IT& begin, const IT& pivot, const IT& end)
51  {
52  if (std::distance(begin, pivot) < 1 || std::distance(pivot, end) < 1)
53  return;
54 
55  // Use first half as receiver
56  for(auto curBegin = begin; curBegin < pivot; ++curBegin)
57  {
58  if (Compare()(*curBegin, *pivot))
59  continue;
60 
61  // Place it at the beginning of the second list
62  std::swap(*curBegin, *pivot);
63 
64  // Displace the higher value in the right place of the second list by swapping
65  auto it = pivot;
66  for (; it != end - 1; ++it)
67  {
68  if (Compare()(*it, *(it + 1)))
69  break;
70 
71  std::swap(*it, *(it + 1));
72  }
73  }
74  }
75  };
76 
93  template <typename IT, typename Compare = std::less<typename std::iterator_traits<IT>::value_type>>
95  {
96  public:
97  void operator()(IT begin, IT middle, IT end)
98  {
99  if (std::distance(begin, middle) < 1 || std::distance(middle, end) < 1)
100  return;
101 
102  // Create buffer with appropriate space
103  std::vector<typename std::iterator_traits<IT>::value_type> buffer;
104  buffer.resize(std::distance(begin, end));
105  auto buffIt = buffer.begin();
106  auto tmpBegin = begin;
107 
108  // Merge into the buffer array taking one by one the lowest sequence element
109  const auto curMiddle(middle);
110  while (begin != curMiddle && middle != end)
111  {
112  if (Compare()(*begin, *middle))
113  *buffIt++ = *begin++;
114  else
115  *buffIt++ = *middle++;
116  }
117 
118  // Finish remaining list into the buffer
119  for (; begin != curMiddle; ++buffIt, ++begin)
120  *buffIt = *begin;
121  for (; middle != end; ++buffIt, ++middle)
122  *buffIt = *middle;
123 
124  // Refill array given the right position
125  for (buffIt = buffer.begin(); buffIt != buffer.end(); ++buffIt, ++tmpBegin)
126  *tmpBegin = *buffIt;
127  }
128  };
129 
140  template <typename IT, typename Aggregator = MergeWithBuffer<IT>>
141  void MergeSort(const IT& begin, const IT& end)
142  {
143  const auto ksize = static_cast<const int>(std::distance(begin, end));
144  if (ksize < 2)
145  return;
146 
147  auto pivot = begin + ksize / 2;
148 
149  // Recursively break the vector into two pieces
150  MergeSort<IT, Aggregator>(begin, pivot);
151  MergeSort<IT, Aggregator>(pivot, end);
152 
153  // Merge the two pieces
154  Aggregator()(begin, pivot, end);
155  }
156  }
157 }
158 
159 #endif // MODULE_SORT_MERGE_HXX
void operator()(IT begin, IT middle, IT end)
Definition: merge.hxx:97
void operator()(const IT &begin, const IT &pivot, const IT &end)
Definition: merge.hxx:50
void MergeSort(const IT &begin, const IT &end)
Definition: merge.hxx:141