Spec-Zone.ru › C++

std::set_symmetric_difference

Определён в заголовочном файле <algorithm>
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt set_symmetric_difference
    ( InputIt1 first1, InputIt1 last1,
      InputIt2 first2, InputIt2 last2,
      OutputIt d_first );
(1) (constexpr since C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 set_symmetric_difference
    ( ExecutionPolicy&& policy,
      ForwardIt1 first1, ForwardIt1 last1,
      ForwardIt2 first2, ForwardIt2 last2,
      ForwardIt3 d_first );
(2) (since C++17)
template< class InputIt1, class InputIt2,
          class OutputIt, class Compare >
OutputIt set_symmetric_difference
    ( InputIt1 first1, InputIt1 last1,
      InputIt2 first2, InputIt2 last2,
      OutputIt d_first, Compare comp );
(3) (constexpr since C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2,
          class ForwardIt3, class Compare >
ForwardIt3 set_symmetric_difference
    ( ExecutionPolicy&& policy,
      ForwardIt1 first1, ForwardIt1 last1,
      ForwardIt2 first2, ForwardIt2 last2,
      ForwardIt3 d_first, Compare comp );
(4) (since C++17)

Вычисляет симметрическую разность двух отсортированных диапазонов: элементы, которые присутствуют в одном из диапазонов, но не в обоих, копируются в диапазон, начинающийся с d_first. Выходной диапазон также сортируется.

Если [first1, last1) содержит m элементов, эквивалентных друг другу, а [first2, last2) содержит n элементов, эквивалентных им, то std::abs(m - n) этих элементов будут скопированы в выходной диапазон с сохранением порядка:

  • если m > n, последние m - n из этих элементов из [first1, last1).
  • если m < n, последние n - m из этих элементов из [first2, last2).
1) Если [first1, last1) или [first2, last2) не отсортирован относительно operator<(until C++20)std::less{}(since C++20), поведение не определено.
3) Если [first1, last1) или [first2, last2) не отсортирован относительно comp, поведение не определено.
2,4) То же, что и (1,3), но выполняется в соответствии с policy.
Эти перегрузки участвуют в разрешении перегрузки, только если значение следующего выражения равно true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(until C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(since C++20)

Если выходной диапазон перекрывается с [first1, last1) или [first2, last2), поведение не определено.

Параметры

first1, last1 - пара итераторов, задающая первый отсортированный диапазон элементов
first2, last2 - пара итераторов, задающая второй отсортированный диапазон элементов
d_first - начало выходного диапазона
policy - используемая политика выполнения
comp - объект функции сравнения (то есть объект, удовлетворяющий требованиям Compare), который возвращает ​true, если первый аргумент меньше второго (то есть упорядочен перед ним).

Сигнатура функции сравнения должна быть эквивалентна следующей:

boolcmp(constType1&a,constType2&b);

Хотя сигнатура не обязана содержать const&, функция не должна изменять переданные ей объекты и должна принимать любые значения типов (возможно, константных) Type1 и Type2 независимо от категории значения (поэтому Type1& не допускается, как и Type1, за исключением случаев, когда для Type1 перемещение эквивалентно копированию(since C++11)).
Типы Type1 и Type2 должны быть такими, чтобы объекты типов InputIt1 и InputIt2 можно было разыменовать, а полученные значения — неявно преобразовать как в Type1, так и в Type2. ​

Требования к типам
-InputIt1, InputIt2 должен соответствовать требованиям LegacyInputIterator.
-OutputIt должен соответствовать требованиям LegacyOutputIterator.
-ForwardIt1, ForwardIt2, ForwardIt3 должен соответствовать требованиям LegacyForwardIterator.
-Compare должен соответствовать требованиям Compare.

Возвращаемое значение

Итератор, указывающий за конец построенного диапазона.

Сложность

Обозначим \(\scriptsize N_1\)N1 как std::distance(first1, last1), а \(\scriptsize N_2\)N2 как std::distance(first2, last2):

1,2) Не более \(\scriptsize 2 \cdot (N_1+N_2)-1\)2⋅(N1+N2)-1 сравнений с использованием operator<(until C++20)std::less{}(since C++20).
3,4) Не более \(\scriptsize 2 \cdot (N_1+N_2)-1\)2⋅(N1+N2)-1 вызовов функции сравнения comp.

Исключения

Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:

  • Если при выполнении функции, вызванной в рамках алгоритма, выбрасывается исключение и ExecutionPolicy — одна из стандартных политик, вызывается std::terminate. Для любого другого ExecutionPolicy поведение определяется реализацией.
  • Если алгоритму не удаётся выделить память, выбрасывается std::bad_alloc.

Возможная реализация

set_symmetric_difference (1)
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt set_symmetric_difference(InputIt1 first1, InputIt1 last1,
                                  InputIt2 first2, InputIt2 last2, OutputIt d_first)
{
    while (first1 != last1)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        
        if (*first1 < *first2)
            *d_first++ = *first1++;
        else
        {
            if (*first2 < *first1)
                *d_first++ = *first2;
            else
                ++first1;
            ++first2;
        }
    }
    return std::copy(first2, last2, d_first);
}
set_symmetric_difference (3)
template<class InputIt1, class InputIt2, class OutputIt, class Compare>
OutputIt set_symmetric_difference(InputIt1 first1, InputIt1 last1,
                                  InputIt2 first2, InputIt2 last2,
                                  OutputIt d_first, Compare comp)
{
    while (first1 != last1)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        
        if (comp(*first1, *first2))
            *d_first++ = *first1++;
        else
        {
            if (comp(*first2, *first1))
                *d_first++ = *first2;
            else
                ++first1;
            ++first2;
        }
    }
    return std::copy(first2, last2, d_first);
}

Пример

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

int main()
{
    std::vector<int> v1{1, 2, 3, 4, 5, 6, 7, 8};
    std::vector<int> v2{5, 7, 9, 10};
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());
    
    std::vector<int> v_symDifference;
    
    std::set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(),
                                  std::back_inserter(v_symDifference));
    
    for (int n : v_symDifference)
        std::cout << n << ' ';
    std::cout << '\n';
}

Вывод:

1 2 3 4 6 8 9 10

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющих поведение, были применены задним числом к ранее опубликованным стандартам C++.

DR Применяется к Опубликованное поведение Исправленное поведение
LWG 291 C++98 не было указано, как обрабатывать эквивалентные элементы во входных диапазонах указано

См. также

includes
определяет, является ли одна последовательность подпоследовательностью другой
(шаблон функции и объект-функция алгоритма)
ranges::includes
(C++20)
set_difference
вычисляет разность двух множеств
(шаблон функции и объект-функция алгоритма)
ranges::set_difference
(C++20)
set_union
вычисляет объединение двух множеств
(шаблон функции и объект-функция алгоритма)
ranges::set_union
(C++20)
set_intersection
вычисляет пересечение двух множеств
(шаблон функции и объект-функция алгоритма)
ranges::set_intersection
(C++20)
ranges::set_symmetric_difference
(C++20)
вычисляет симметрическую разность двух множеств
(объект-функция алгоритма)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/set_symmetric_difference

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API