Namespaces
Variants

std::ranges::equal_range

От ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Немодифицирующие операции над последовательностями    
Пакетные операции
(C++17)
Операции поиска
Модифицирующие операции над последовательностями
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разбиения
(C++11)    

Операции сортировки
Операции бинарного поиска
(по разбитым диапазонам)
Операции над множествами (по отсортированным диапазонам)
Операции слияния (по отсортированным диапазонам)
Операции с кучей
Операции поиска минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановок


Политики выполнения (C++17)
(только для пояснения*)(C++26)

Числовые операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
Ограниченные алгоритмы
Все имена в этом меню принадлежат пространству имён std::ranges
Немодифицирующие операции над последовательностями
Модифицирующие операции над последовательностями
Операции разбиения
Операции сортировки
Операции бинарного поиска (по отсортированным диапазонам)
       
       
Операции над множествами (по отсортированным диапазонам)
Операции с кучей
Операции поиска минимума/максимума
       
       
Операции перестановок
Операции свёртки
Операции над неинициализированной памятью
Типы возврата
 
Определён в заголовочном файле <algorithm>
Сигнатура вызова
template< std::forward_iterator I, std::sentinel_for<I> S,
          class T, class Proj = std::identity,
          std::indirect_strict_weak_order
              <const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr ranges::subrange<I> equal_range( I first, S last, const T& value,
                                           Comp comp = {}, Proj proj = {} );
(1) (начиная с C++20)
(до C++26)
template< std::forward_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          class T = std::projected_value_t<I, Proj>,
          std::indirect_strict_weak_order
              <const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr ranges::subrange<I> equal_range( I first, S last, const T& value,
                                           Comp comp = {}, Proj proj = {} );
(начиная с C++26)
template< ranges::forward_range R,
          class T, class Proj = std::identity,
          std::indirect_strict_weak_order
              <const T*, std::projected<ranges::iterator_t<R>,
                                        Proj>> Comp = ranges::less >
constexpr ranges::borrowed_subrange_t<R>
    equal_range( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
(2) (начиная с C++20)
(до C++26)
template< ranges::forward_range R,
          class Proj = std::identity,
          class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
          std::indirect_strict_weak_order
              <const T*, std::projected<ranges::iterator_t<R>,
                                        Proj>> Comp = ranges::less >
constexpr ranges::borrowed_subrange_t<R>
    equal_range( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
(начиная с C++26)
1) Возвращает представление, содержащее все элементы, эквивалентные value в диапазоне [first, last).

Диапазон [first, last) должен быть по крайней мере частично упорядочен относительно value, то есть он должен удовлетворять всем следующим требованиям:

  • разбит относительно element < value или comp(element, value) (то есть все элементы, для которых выражение истинно true, предшествуют всем элементам, для которых выражение ложно false).
  • разбит относительно !(value < element) или !comp(value, element).
  • для всех элементов, если element < value или comp(element, value) истинно true, то !(value < element) или !comp(value, element) также истинно true.

Полностью отсортированный диапазон удовлетворяет этим критериям.

Возвращаемое представление создаётся из двух итераторов: первый указывает на первый элемент, который не меньше чем value, а второй — на первый элемент, который больше чем value. Первый итератор может быть также получен с помощью std::ranges::lower_bound(), второй — с помощью std::ranges::upper_bound().

2) То же, что и (1), но использует r в качестве исходного диапазона, как если бы использовался диапазон ranges::begin(r) как first и ranges::end(r) как last.

Объекты, подобные функциям, описанные на этой странице, являются объектами функций алгоритмов (неофициально известными как niebloids), то есть:

Параметры

first, last - пара итератор-страж, определяющая диапазон элементов для исследования
r - диапазон элементов для исследования
value - значение для сравнения элементов
comp - если первый аргумент меньше (то есть упорядочен перед) второго
proj - проекция для применения к элементам

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

std::ranges::subrange, содержащий пару итераторов, определяющую искомый диапазон: первый указывает на первый элемент, который не меньше чем value, а второй указывает на первый элемент больше чем value.

Если нет элементов не меньше чем value, то в качестве первого элемента возвращается последний итератор (итератор, равный last или ranges::end(r)). Аналогично, если нет элементов больше чем value, то в качестве второго элемента возвращается последний итератор.

Сложность

Количество сравнений логарифмическое по расстоянию между first и last (не более 2 * log2(last - first) + O(1) сравнений). Однако для итератора, не моделирующего random_access_iterator, количество инкрементов итератора линейно.

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

struct equal_range_fn
{
    template<std::forward_iterator I, std::sentinel_for<I> S,
             class Proj = std::identity, class T = std::projected_value_t<I, Proj>,
             std::indirect_strict_weak_order
                 <const T*, std::projected<I, Proj>> Comp = ranges::less>
    constexpr ranges::subrange<I>
        operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const
    {
        return ranges::subrange
        (
            ranges::lower_bound(first, last, value, std::ref(comp), std::ref(proj)),
            ranges::upper_bound(first, last, value, std::ref(comp), std::ref(proj))
        );
    }
 
    template<ranges::forward_range R, class Proj = std::identity,
             class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
             std::indirect_strict_weak_order
                 <const T*, std::projected<ranges::iterator_t<R>,
                                           Proj>> Comp = ranges::less>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), value,
                       std::ref(comp), std::ref(proj));
    }
};
 
inline constexpr equal_range_fn equal_range;

Примечания

Макрос проверки возможностей Значение Std Возможность
__cpp_lib_algorithm_default_value_type 202403 (C++26) Инициализация списком для алгоритмов (1,2)

Пример

#include <algorithm>
#include <compare>
#include <complex>
#include <iostream>
#include <vector>

struct S
{
    int number {};
    char name {};
    // note: name is ignored by these comparison operators
    friend bool operator== (const S s1, const S s2) { return s1.number == s2.number; }
    friend auto operator<=>(const S s1, const S s2) { return s1.number <=> s2.number; }
    friend std::ostream& operator<<(std::ostream& os, S o)
    {
        return os << '{' << o.number << ", '" << o.name << "'}";
    }
};

void println(auto rem, const auto& v)
{
    for (std::cout << rem; const auto& e : v)
        std::cout << e << ' ';
    std::cout << '\n';
}

int main()
{
    // note: not ordered, only partitioned w.r.t. S defined below
    std::vector<S> vec
    {
        {1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {4, 'D'}, {4,'G'}, {3,'F'}
    };
    
    const S value{2, '?'};
    
    namespace ranges = std::ranges;
    
    auto a = ranges::equal_range(vec, value);
    println("1. ", a);
    
    auto b = ranges::equal_range(vec.begin(), vec.end(), value);
    println("2. ", b);
    
    auto c = ranges::equal_range(vec, 'D', ranges::less {}, &S::name);
    println("3. ", c);
    
    auto d = ranges::equal_range(vec.begin(), vec.end(), 'D', ranges::less {}, &S::name);
    println("4. ", d);

    using CD = std::complex<double>;
    std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}};
    auto cmpz = [](CD x, CD y) { return x.real() < y.real(); };
    #ifdef __cpp_lib_algorithm_default_value_type
        auto p3 = ranges::equal_range(nums, {2, 0}, cmpz);
    #else
        auto p3 = ranges::equal_range(nums, CD{2, 0}, cmpz);
    #endif
    println("5. ", p3);
}

Вывод:

1. {2, 'B'} {2, 'C'} {2, 'D'}
2. {2, 'B'} {2, 'C'} {2, 'D'}
3. {2, 'D'} {4, 'D'}
4. {2, 'D'} {4, 'D'}
5. (2,2) (2,1)

Смотри также

находит первый элемент, не меньший заданного значения, используя бинарный поиск
(объект функции алгоритма)
находит первый элемент, больший заданного значения, используя бинарный поиск
(объект функции алгоритма)
определяет, существует ли элемент в диапазоне, используя бинарный поиск
(объект функции алгоритма)
делит диапазон элементов на две группы
(объект функции алгоритма)
определяет, являются ли два набора элементов одинаковыми
(объект функции алгоритма)
находит диапазон элементов, соответствующих заданному значению, используя бинарный поиск
(функция-шаблон)