std::ranges::set_union, std::ranges::set_union_result
| (C++23) <algorithm>
|
||
| 헤더 |
||
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 set_union_result<I1, I2, O>
set_union( I1 first1, S1 last1, I2 first2, S2 last2,
O result, Comp comp = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
|
에 정의됨 | 호출 서명 |
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 set_union_result<ranges::borrowed_iterator_t<R1>,
ranges::borrowed_iterator_t<R2>, O>
set_union( R1&& r1, R2&& r2, O result, Comp comp = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
|
(1) | (C++20부터) |
| (2) |
||
template< class I1, class I2, class O >
using set_union_result = ranges::in_in_out_result<I1, I2, O>;
|
(C++20부터) | 헬퍼 타입 |
(3)result(C++20부터)[first1, last1)[first2, last2)의 정렬된 합집합을 구성합니다. 이 합집합은 정렬된 두 입력 범위
과 m(또는 둘 중 하나)에 있는 요소들의 집합으로 구성됩니다.
[first1, last1)요소가 n에서 [first2, last2)번, m에서 [first1, last1)번 발견되면, result에서 max(n - m, 0)로 모든 [first2, last2)개의 요소가 순서를 유지하며 복사되고, 그런 다음 result에서
로 정확히
- 개의 요소가 마찬가지로 순서를 유지하며 복사됩니다.
comp다음의 경우 동작이 정의되지 않습니다:proj1입력 범위가 각각proj2및 - 또는
comp1)r1과 동일하지만, 첫 번째 범위로 r2을 사용하고 두 번째 범위로 ranges::begin(r1)을 사용합니다. 마치 first1을 ranges::end(r1)로, last1을 ranges::begin(r2)로, first2을 ranges::end(r2)로, last2을 로 사용하는 것과 같습니다.이 페이지에 설명된 함수 유사 개체는 알고리즘 함수 객체 (비공식적으로 niebloids
- 라고 함)입니다. 즉:
- 이들 중 하나를 호출할 때 명시적 템플릿 인자 목록을 지정할 수 없습니다.이들 중 어느 것도 인자 종속 조회
- 에 보이지 않습니다.이들 중 하나가 일반 비한정 조회에 의해 함수 호출 연산자 왼쪽의 이름으로 발견되면, 인자 종속 조회
매개변수
| first1, last1 | - | 첫 번째 입력 정렬된 range 의 요소들을 정의하는 iterator-sentinel 쌍 |
| first2, last2 | - | 두 번째 입력 정렬된 range 의 요소들을 정의하는 iterator-sentinel 쌍 |
| r1 | - | 첫 번째 입력 정렬 범위 |
| r2 | - | 두 번째 입력 정렬 범위 |
| result | - | 출력 범위의 시작점 |
| comp | - | 투영된 요소들에 적용할 비교 연산 |
| proj1 | - | 첫 번째 범위의 요소들에 적용할 투영(projection) |
| proj2 | - | 두 번째 범위의 요소들에 적용할 투영(projection) |
반환값
{ last1, last2, result_last } , 여기서 result_last 는 구성된 범위의 끝입니다.
복잡도
최대 2·(N 1 +N 2 )-1 번의 비교와 각 프로젝션의 적용이 필요하며, 여기서 N 1 과 N 2 는 각각 ranges:: distance ( first1, last1 ) 와 ranges:: distance ( first2, last2 ) 입니다.
참고 사항
이 알고리즘은
ranges::merge
가 수행하는 작업과 유사한 작업을 수행합니다. 두 알고리즘 모두 정렬된 두 입력 범위를 소비하여 두 입력의 요소들로 구성된 정렬된 출력을 생성합니다. 이 두 알고리즘의 차이는 동등하게 비교되는 값들(양쪽 입력 범위에서 나온 값들)을如何处理하는지에 있습니다(
LessThanComparable
에 대한 참고 사항 참조). 만약 동등한 값들이 첫 번째 범위에서
n
번, 두 번째 범위에서
m
번 나타난다면,
ranges::merge
는
n
+
m
개의 모든 발생을 출력하는 반면,
ranges::set_union
은
std::
max
(
n, m
)
개만 출력합니다. 따라서
ranges::merge
는 정확히
(N
1
+N
2
)
개의 값을 출력하지만,
ranges::set_union
은 더 적은 수를 생성할 수 있습니다.
가능한 구현
struct set_union_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::set_union_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(proj1, *first1), std::invoke(proj2, *first2))) { *result = *first1; ++first1; } else if (std::invoke(comp, std::invoke(proj2, *first2), std::invoke(proj1, *first1))) { *result = *first2; ++first2; } else { *result = *first1; ++first1; ++first2; } } auto res1 = ranges::copy(std::move(first1), std::move(last1), std::move(result)); auto res2 = ranges::copy(std::move(first2), std::move(last2), std::move(res1.out)); return {std::move(res1.in), std::move(res2.in), std::move(res2.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::set_union_result<ranges::borrowed_iterator_t (설명: HTML 태그와 속성은 그대로 유지되었으며, C++ 관련 용어인 `ranges::borrowed_iterator_t`는 번역되지 않았습니다. 링크 구조와 CSS 클래스도 원본 형식을 그대로 보존하였습니다.)<R1>, ranges::borrowed_iterator_t (설명: HTML 태그와 속성은 그대로 유지되었으며, C++ 관련 용어인 `ranges::borrowed_iterator_t`는 번역되지 않았습니다. 링크 구조와 CSS 클래스도 원본 형식을 그대로 보존하였습니다.)<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 set_union_fn set_union {}; |
예제
#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 << "} ∪ { "; 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::set_union(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::set_union(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 4 5 6 7 }
{ 1 2 3 4 5 5 5 } ∪ { 3 4 5 6 7 } =
{ 1 2 3 4 5 5 5 6 7 }
참고 항목
(C++20) |
두 집합의 차집합을 계산합니다 (알고리즘 함수 객체) |
(C++20) |
두 집합의 교집합을 계산합니다 (알고리즘 함수 객체) |
| 두 집합의 대칭 차집합을 계산합니다 (알고리즘 함수 객체) | |
(C++20) |
두 정렬된 범위를 병합합니다 (알고리즘 함수 객체) |
(C++20) |
한 시퀀스가 다른 시퀀스의 부분 수열인지 결정합니다 (알고리즘 함수 객체) |
| 두 집합의 합집합을 계산합니다 (함수 템플릿) |