MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
merge.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_ALGORITHM_MERGE_HPP__
2#define MSTL_CORE_ALGORITHM_MERGE_HPP__
3
11
14
20
43template <typename Iterator1, typename Iterator2, typename Iterator3, typename Compare,
45constexpr Iterator3 merge(Iterator1 first1, Iterator1 last1, Iterator2 first2,
46 Iterator2 last2, Iterator3 result, Compare comp) {
47 while (first1 != last1 && first2 != last2) {
48 if (comp(*first2, *first1)) {
49 *result = *first2;
50 ++first2;
51 } else {
52 *result = *first1;
53 ++first1;
54 }
55 ++result;
56 }
57 return _MSTL copy(first2, last2, _MSTL copy(first1, last1, result));
58}
59
72template <typename Iterator1, typename Iterator2, typename Iterator3>
73constexpr Iterator3 merge(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Iterator3 result) {
74 return _MSTL merge(first1, last1, first2, last2, result, _MSTL less<iter_value_t<Iterator1>>());
75}
76
79
94template <typename Iterator, typename Distance, typename Compare>
95constexpr void __merge_without_buffer_aux(Iterator first, Iterator middle, Iterator last,
96 Distance len1, Distance len2, Compare comp) {
97 if (len1 == 0 || len2 == 0) return;
98 if (len1 + len2 == 2) {
99 if (comp(*middle, *first)) _MSTL iter_swap(first, middle);
100 return;
101 }
102 Iterator first_cut = first;
103 Iterator second_cut = middle;
104 Distance len11 = 0;
105 Distance len22 = 0;
106 if (len1 > len2) {
107 len11 = len1 / 2;
108 _MSTL advance(first_cut, len11);
109 second_cut = _MSTL lower_bound(middle, last, *first_cut, comp);
110 len22 = _MSTL distance(middle, second_cut);
111 } else {
112 len22 = len2 / 2;
113 _MSTL advance(second_cut, len22);
114 first_cut = _MSTL upper_bound(first, middle, *second_cut, comp);
115 len11 = _MSTL distance(first, first_cut);
116 }
117 _MSTL rotate(first_cut, middle, second_cut);
118 Iterator new_middle = first_cut;
119 _MSTL advance(new_middle, len22);
120 _INNER __merge_without_buffer_aux(first, first_cut, new_middle, len11, len22, comp);
121 _INNER __merge_without_buffer_aux(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
122}
123
140template <typename Iterator1, typename Iterator2, typename Distance>
141constexpr Iterator1 __rotate_with_buffer_aux(Iterator1 first, Iterator1 middle, Iterator1 last,
142 Distance len1, Distance len2, Iterator2 buffer, Distance buffer_size) {
143 Iterator2 buffer_end;
144 if (len1 > len2 && len2 <= buffer_size) {
145 buffer_end = _MSTL copy(middle, last, buffer);
146 _MSTL copy_backward(first, middle, last);
147 return _MSTL copy(buffer, buffer_end, first);
148 }
149 if (len1 <= buffer_size) {
150 buffer_end = _MSTL copy(first, middle, buffer);
151 _MSTL copy(middle, last, first);
152 return _MSTL copy_backward(buffer, buffer_end, last);
153 }
154 _MSTL rotate(first, middle, last);
155 _MSTL advance(first, len2);
156 return first;
157}
158
176template <typename Iterator, typename Distance, typename Pointer, typename Compare>
177constexpr void __merge_with_buffer_aux(Iterator first, Iterator middle, Iterator last,
178 Distance len1, Distance len2, Pointer buffer, Distance buffer_size, Compare comp) {
179 if (len1 <= len2 && len1 <= buffer_size) {
180 Pointer end_buffer = _MSTL copy(first, middle, buffer);
181 _MSTL merge(buffer, end_buffer, middle, last, first, comp);
182 }
183 else if (len2 <= buffer_size) {
184 Pointer end_buffer = _MSTL copy(middle, last, buffer);
185 if (first == middle) {
186 _MSTL copy_backward(buffer, end_buffer, last);
187 return;
188 }
189 if (buffer == end_buffer) {
190 _MSTL copy_backward(first, middle, last);
191 return;
192 }
193 --middle;
194 --end_buffer;
195 while (true) {
196 if (comp(*end_buffer, *middle)) {
197 *--last = *middle;
198 if (first == middle) {
199 _MSTL copy_backward(buffer, ++end_buffer, last);
200 return;
201 }
202 --middle;
203 }
204 else {
205 *--last = *end_buffer;
206 if (buffer == end_buffer) {
207 _MSTL copy_backward(first, ++middle, last);
208 return;
209 }
210 --end_buffer;
211 }
212 }
213 }
214 else {
215 Iterator first_cut = first;
216 Iterator second_cut = middle;
217 Distance len11 = 0;
218 Distance len22 = 0;
219 if (len1 > len2) {
220 len11 = len1 / 2;
221 _MSTL advance(first_cut, len11);
222 second_cut = _MSTL lower_bound(middle, last, *first_cut, comp);
223 len22 = _MSTL distance(middle, second_cut);
224 } else {
225 len22 = len2 / 2;
226 _MSTL advance(second_cut, len22);
227 first_cut = _MSTL upper_bound(first, middle, *second_cut, comp);
228 len11 = _MSTL distance(first, first_cut);
229 }
230 Iterator new_middle = _INNER __rotate_with_buffer_aux(
231 first_cut, middle, second_cut, len1 - len11, len22, buffer, buffer_size);
232
233 _INNER __merge_with_buffer_aux(
234 first, first_cut, new_middle, len11, len22, buffer, buffer_size, comp);
235 _INNER __merge_with_buffer_aux(
236 new_middle, second_cut, last, len1 - len11, len2 - len22, buffer, buffer_size, comp);
237 }
238}
239
242
257template <typename Iterator, typename Compare, enable_if_t<is_ranges_bid_iter_v<Iterator>, int> = 0>
258constexpr void inplace_merge(Iterator first, Iterator middle, Iterator last, Compare comp) {
259 if (first == middle || middle == last) return;
260 using Distance = iter_difference_t<Iterator>;
261 Distance len1 = _MSTL distance(first, middle);
262 Distance len2 = _MSTL distance(middle, last);
263 try {
264 temporary_buffer<Iterator> buffer(first, last);
265 _INNER __merge_with_buffer_aux(
266 first, middle, last, len1, len2,
267 buffer.begin(), Distance(buffer.size()), comp
268 );
269 } catch (...) {
270 _INNER __merge_without_buffer_aux(first, middle, last, len1, len2, comp);
271 }
272}
273
281template <typename Iterator>
282constexpr void inplace_merge(Iterator first, Iterator middle, Iterator last) {
283 return _MSTL inplace_merge(first, middle, last, _MSTL less<iter_value_t<Iterator>>());
284}
285 // MergeAlgorithms
287
289#endif // MSTL_CORE_ALGORITHM_MERGE_HPP__
constexpr Iterator lower_bound(Iterator first, Iterator last, const T &value, Compare comp)
查找有序范围中第一个不小于指定值的元素位置
constexpr Iterator upper_bound(Iterator first, Iterator last, const T &value, Compare comp)
查找有序范围中第一个大于指定值的元素位置
MSTL_INLINE17 constexpr bool is_ranges_fwd_iter_v
检查是否为范围前向迭代器
constexpr iter_difference_t< Iterator > distance(Iterator first, Iterator last)
计算两个迭代器之间的距离
constexpr void advance(Iterator &i, Distance n)
将迭代器前进指定距离
typename iterator_traits< Iterator >::value_type iter_value_t
获取迭代器的值类型
typename iterator_traits< Iterator >::difference_type iter_difference_t
获取迭代器的差值类型
constexpr void inplace_merge(Iterator first, Iterator middle, Iterator last, Compare comp)
原地合并两个已排序的连续范围
constexpr Iterator3 merge(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Iterator3 result, Compare comp)
合并两个已排序序列
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
constexpr void iter_swap(Iterator1 a, Iterator2 b) noexcept(noexcept(_MSTL swap(*a, *b)))
交换迭代器指向的元素
constexpr Iterator2 copy_backward(Iterator1 first, Iterator1 last, Iterator2 result)
反向复制范围元素
constexpr void rotate(Iterator first, Iterator middle, Iterator last)
旋转范围元素
constexpr Iterator2 copy(Iterator1 first, Iterator1 last, Iterator2 result)
复制范围元素
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
小于比较仿函数
MSTL_NODISCARD MSTL_CONSTEXPR20 size_type size() const noexcept
获取缓冲区实际大小
MSTL_NODISCARD MSTL_CONSTEXPR20 pointer begin() noexcept
获取缓冲区起始迭代器
MSTL临时缓冲区