Spec-Zone.ru › C++

std::adjacent_find

Определено в заголовке <algorithm>
(1)
template< class ForwardIt >
ForwardIt adjacent_find( ForwardIt first, ForwardIt last );
(до C++20)
template< class ForwardIt >
constexpr ForwardIt adjacent_find( ForwardIt first, ForwardIt last );
(с C++20)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt adjacent_find( ExecutionPolicy&& policy,
                         ForwardIt first, ForwardIt last );
(2) (с C++17)
(3)
template< class ForwardIt, class BinaryPredicate >
ForwardIt adjacent_find( ForwardIt first, ForwardIt last, BinaryPredicate p );
(до C++20)
template< class ForwardIt, class BinaryPredicate >
constexpr ForwardIt adjacent_find( ForwardIt first, ForwardIt last,
                                   BinaryPredicate p );
(с C++20)
template< class ExecutionPolicy, class ForwardIt, class BinaryPredicate >
ForwardIt adjacent_find( ExecutionPolicy&& policy,
                         ForwardIt first, ForwardIt last, BinaryPredicate p );
(4) (с C++17)

Ищет в диапазоне [first, last) две последовательные одинаковые элементы.

1) Элементы сравниваются с помощью operator==.
3) Элементы сравниваются с помощью заданного бинарного предиката p.
2,4) Аналогично (1,3), но выполняется согласно policy. Эти перегрузки не участвуют в разрешении перегрузки, если

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> является true.

(до C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> является true.

(с C++20)

Параметры

first, last - диапазон элементов для проверки
policy - политика выполнения. Подробнее см. политика выполнения.
p - бинарный предикат, возвращающий ​true , если элементы должны рассматриваться как равные.

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

bool pred(const Type1 &a, const Type2 &b);

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

Требования к типу
-ForwardIt должен соответствовать требованиям LegacyForwardIterator.

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

Итератор на первый из первой пары идентичных элементов, то есть первый итератор it такой, что *it == *(it + 1) для (1,2) или p(*it, *(it + 1)) != false для (3,4).

Если такие элементы не найдены, возвращается last.

Сложность

1,3) Ровно std::min((result - first) + 1, (last - first) - 1) применений предиката, где result - это возвращаемое значение.
2,4) O(last - first) применений соответствующего предиката.

Исключения

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

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

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

adjacent_find (1)
template<class ForwardIt>
ForwardIt adjacent_find(ForwardIt first, ForwardIt last)
{
    if (first == last)
        return last;
 
    ForwardIt next = first;
    ++next;
 
    for (; next != last; ++next, ++first)
        if (*first == *next)
            return first;
 
    return last;
}
adjacent_find (3)
template<class ForwardIt, class BinaryPredicate>
ForwardIt adjacent_find(ForwardIt first, ForwardIt last, BinaryPredicate p)
{
    if (first == last)
        return last;
 
    ForwardIt next = first;
    ++next;
 
    for (; next != last; ++next, ++first)
        if (p(*first, *next))
            return first;
 
    return last;
}

Пример

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
 
int main()
{
    std::vector<int> v1 {0, 1, 2, 3, 40, 40, 41, 41, 5};
 
    auto i1 = std::adjacent_find(v1.begin(), v1.end());
 
    if (i1 == v1.end())
        std::cout << "No matching adjacent elements\n";
    else
        std::cout << "The first adjacent pair of equal elements is at "
                  << std::distance(v1.begin(), i1) << ", *i1 = "
                  << *i1 << '\n';
 
    auto i2 = std::adjacent_find(v1.begin(), v1.end(), std::greater<int>());
    if (i2 == v1.end())
        std::cout << "The entire vector is sorted in ascending order\n";
    else
        std::cout << "The last element in the non-decreasing subsequence is at "
                  << std::distance(v1.begin(), i2) << ", *i2 = " << *i2 << '\n';
}

Вывод:

The first adjacent pair of equal elements is at 4, *i1 = 40
The last element in the non-decreasing subsequence is at 7, *i2 = 41

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

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

DR Применено к Поведение, как опубликовано Правильное поведение
LWG 240 C++98 предикат применялся std::find,
(first, last, value) - first раз,
для (1,3), где value никогда не было определено
применялся std::min(,
(result - first) + 1,,
(last - first) - 1) раз

См. также

unique
удаляет последовательные дубликаты элементов в диапазоне
(функция-шаблон)
ranges::adjacent_find
(C++20)
находит первые два смежных элемента, которые равны (или удовлетворяют заданному предикату)
(niebloid)

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

Spec-Zone.ru

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