merge.hxx
Go to the documentation of this file.
1 /*===========================================================================================================
2  *
3  * SHA - Simple Hybesis Algorithms
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/michael-jeulinl/Simple-Hybesis-Algorithms/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 SHA_Sort
27 {
45  template <typename IT>
47  {
48  public:
49  void operator()(IT begin, IT middle, IT end)
50  {
51  if (std::distance(begin, middle) < 1 || std::distance(middle, end) < 1)
52  return;
53 
54  // Use first half as receiver
55  for(; begin < middle; ++begin)
56  {
57  if (*middle >= *begin)
58  continue;
59 
60  typename std::iterator_traits<IT>::value_type value;
61  std::swap(value, *begin); // keep the higher value
62  std::swap(*begin, *middle); // Place it at the beginning of the second list
63 
64  // Displace the higher value in the right place of the second list by swapping
65  auto it = middle;
66  for (; it != end - 1; ++it)
67  {
68  if (*(it + 1) >= value)
69  break;
70 
71  std::swap(*it, *(it + 1));
72  }
73 
74  // Restore the value at his right place
75  std::swap(*it, value);
76  }
77  }
78  };
79 
80 
98  template <typename Container, typename IT>
100  {
101  public:
102  void operator()(IT begin, IT middle, IT end)
103  {
104  if (std::distance(begin, middle) < 1 || std::distance(middle, end) < 1)
105  return;
106 
107  Container buffer;
108  buffer.resize(std::distance(begin, end)); // Reserve right space (e.g. string container)
109  auto buffIt = buffer.begin();
110  auto tmpBegin = begin;
111 
112  // Merge into the buffer array taking one by one the lowest sequence element
113  const auto curMiddle(middle);
114  while (begin != curMiddle && middle != end)
115  {
116  if (*begin <= *middle)
117  *buffIt++ = *begin++;
118  else
119  *buffIt++ = *middle++;
120  }
121 
122  // Finish remaining list into the buffer
123  for (; begin != curMiddle; ++buffIt, ++begin)
124  *buffIt = *begin;
125  for (; middle != end; ++buffIt, ++middle)
126  *buffIt = *middle;
127 
128  // Refill array given the right position
129  for (buffIt = buffer.begin(); buffIt != buffer.end(); ++buffIt, ++tmpBegin)
130  *tmpBegin = *buffIt;
131  }
132  };
133 
147  template <typename Container, typename IT, typename Aggregator = MergeWithBuffer<Container, IT>>
148  void MergeSort(const IT& begin, const IT& end)
149  {
150  const auto ksize = static_cast<const int>(std::distance(begin, end));
151  if (ksize < 2)
152  return;
153 
154  auto middle = begin + ksize / 2;
155 
156  // Recursively break the vector into two pieces
157  MergeSort<Container, IT, Aggregator>(begin, middle);
158  MergeSort<Container, IT, Aggregator>(middle, end);
159 
160  // Merge the two pieces
161  Aggregator()(begin, middle, end);
162  }
163 }
164 
165 #endif // MODULE_SORT_MERGE_HXX
void operator()(IT begin, IT middle, IT end)
Definition: merge.hxx:102
void MergeSort(const IT &begin, const IT &end)
Definition: merge.hxx:148
void operator()(IT begin, IT middle, IT end)
Definition: merge.hxx:49