std::ranges:: merge, std::ranges:: merge_result
|
헤더 파일에 정의됨
<algorithm>
|
||
|
호출 시그니처
|
||
|
template
<
std::
input_iterator
I1,
std::
sentinel_for
<
I1
>
S1,
std::
input_iterator
I2,
std::
sentinel_for
<
I2
>
S2,
|
(1) | (C++20 이후) |
|
template
<
ranges::
input_range
R1,
ranges::
input_range
R2,
std::
weakly_incrementable
O,
class
Comp
=
ranges::
less
,
|
(2) | (C++20 이후) |
|
헬퍼 타입
|
||
|
template
<
class
I1,
class
I2,
class
O
>
using merge_result = ranges:: in_in_out_result < I1, I2, O > ; |
(3) | (C++20 이후) |
두 개의
정렬된
범위
[
[
first1
,
last1
)
와
[
first2
,
last2
)
를
result
에서 시작하는 하나의
정렬된
범위로 병합합니다.
시퀀스가 비교자
comp
에 대해
정렬되었다
고 말하려면, 시퀀스를 가리키는 임의의 반복자
it
와
it + n
가 시퀀스의 요소를 가리키는 유효한 반복자가 되도록 하는 임의의 음이 아닌 정수
n
에 대해,
std::
invoke
(
comp,
std::
invoke
(
proj2,
*
(
it
+
n
)
)
,
std::
invoke
(
proj1,
*
it
)
)
)
가
false
로 평가되어야 합니다.
대상 범위가 입력 범위 중 하나와 겹치는 경우(입력 범위끼리는 서로 겹칠 수 있음) 동작은 정의되지 않습니다.
이 병합 함수는 안정적(stable) 입니다. 이는 원본 두 범위에서 동등한 요소들에 대해, 첫 번째 범위의 요소들(원래 순서를 유지하며)이 두 번째 범위의 요소들(원래 순서를 유지하며)보다 앞에 위치함을 의미합니다.
이 페이지에서 설명하는 함수형 개체들은 algorithm function objects (일반적으로 niebloids 로 알려진)입니다. 즉:
- 명시적 템플릿 인수 목록은 이들 중 어느 것을 호출할 때도 지정할 수 없습니다.
- 이들 중 어느 것도 인수 의존 이름 검색 에 보이지 않습니다.
- 이들 중 어느 것이 함수 호출 연산자의 왼쪽 이름으로 일반 비한정 이름 검색 에 의해 발견될 때, 인수 의존 이름 검색 이 억제됩니다.
목차 |
매개변수
| first1, last1 | - | 병합할 첫 번째 입력 정렬된 범위 를 정의하는 반복자-감시자 쌍 |
| first2, last2 | - | 병합할 두 번째 입력 정렬된 범위 를 정의하는 반복자-감시자 쌍 |
| result | - | 출력 범위의 시작점 |
| comp | - | 투영된 요소들에 적용할 비교 함수 |
| proj1 | - | 첫 번째 범위의 요소들에 적용할 투영 함수 |
| proj2 | - | 두 번째 범위의 요소들에 적용할 투영 함수 |
반환값
{ last1, last2, result_last } , 여기서 result_last 는 구성된 범위의 끝입니다.
복잡도
최대 N − 1 번의 비교와 각 projection의 적용, 여기서 N = ranges:: distance ( first1, last1 ) + ranges:: distance ( first2, last12 ) 입니다.
참고 사항
이 알고리즘은 ranges:: set_union 가 수행하는 작업과 유사합니다. 두 알고리즘 모두 정렬된 두 입력 범위를 소비하며 두 입력의 요소들로 구성된 정렬된 출력을 생성합니다. 이 두 알고리즘의 차이는 동등하게 비교되는 값들( LessThanComparable 에 대한 참고 사항 참조)을 처리하는 방식에 있습니다. 만약 동등한 값들이 첫 번째 범위에서 n 번 나타나고 두 번째 범위에서 m 번 나타난다면, ranges::merge 는 n + m 개의 모든 발생을 출력하는 반면, ranges::set_union 는 max ( n, m ) 개만 출력합니다. 따라서 ranges::merge 는 정확히 N 개의 값을 출력하고 ranges::set_union 는 더 적은 수를 출력할 수 있습니다.
가능한 구현
struct merge_fn { template<std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, std::weakly_incrementable O, class Comp = ranges::less, class Proj1 = std::identity, class Proj2 = std::identity> requires std::mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr ranges::merge_result<I1, I2, O> operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { for (; !(first1 == last1 or first2 == last2); ++result) { if (std::invoke(comp, std::invoke(proj2, *first2), std::invoke(proj1, *first1))) *result = *first2, ++first2; else *result = *first1, ++first1; } auto ret1{ranges::copy(std::move(first1), std::move(last1), std::move(result))}; auto ret2{ranges::copy(std::move(first2), std::move(last2), std::move(ret1.out))}; return {std::move(ret1.in), std::move(ret2.in), std::move(ret2.out)}; } template<ranges::input_range R1, ranges::input_range R2, std::weakly_incrementable O, class Comp = ranges::less, class Proj1 = std::identity, class Proj2 = std::identity> requires std::mergeable<ranges::iterator_t<R1>, ranges::iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr ranges::merge_result<ranges::borrowed_iterator_t<R1>, ranges::borrowed_iterator_t<R2>, O> operator()(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), std::move(result), std::move(comp), std::move(proj1), std::move(proj2)); } }; inline constexpr merge_fn merge {}; |
예제
#include <algorithm> #include <iostream> #include <iterator> #include <vector> void print(const auto& in1, const auto& in2, auto first, auto last) { std::cout << "{ "; for (const auto& e : in1) std::cout << e << ' '; std::cout << "} +\n{ "; for (const auto& e : in2) std::cout << e << ' '; std::cout << "} =\n{ "; while (!(first == last)) std::cout << *first++ << ' '; std::cout << "}\n\n"; } int main() { std::vector<int> in1, in2, out; in1 = {1, 2, 3, 4, 5}; in2 = {3, 4, 5, 6, 7}; out.resize(in1.size() + in2.size()); const auto ret = std::ranges::merge(in1, in2, out.begin()); print(in1, in2, out.begin(), ret.out); in1 = {1, 2, 3, 4, 5, 5, 5}; in2 = {3, 4, 5, 6, 7}; out.clear(); out.reserve(in1.size() + in2.size()); std::ranges::merge(in1, in2, std::back_inserter(out)); print(in1, in2, out.cbegin(), out.cend()); }
출력:
{ 1 2 3 4 5 } +
{ 3 4 5 6 7 } =
{ 1 2 3 3 4 4 5 5 6 7 }
{ 1 2 3 4 5 5 5 } +
{ 3 4 5 6 7 } =
{ 1 2 3 3 4 4 5 5 5 5 6 7 }
참고 항목
|
(C++20)
|
두 개의 정렬된 범위를 제자리에서 병합
(알고리즘 함수 객체) |
|
(C++20)
|
범위가 오름차순으로 정렬되었는지 확인
(알고리즘 함수 객체) |
|
(C++20)
|
두 집합의 합집합을 계산
(알고리즘 함수 객체) |
|
(C++20)
|
범위를 오름차순으로 정렬
(알고리즘 함수 객체) |
|
(C++20)
|
동일한 요소들 사이의 순서를 유지하며 범위를 정렬
(알고리즘 함수 객체) |
|
두 개의 정렬된 범위를 병합
(함수 템플릿) |