Как выполнить двоичный поиск в std::vector, НО, который возвращает RandomAccessIterator?

Я ищу log2(N) способ поиска std::vector и получения RandomAccessIterator. Я хочу, чтобы он работал точно так же, как std::lower_bound(), но возвращал RandomAccessIterator вместо ForwardIterator.

Мне нужен результат первого поиска std::vector, чтобы определить поддиапазон большего второго std::vector. Я хочу использовать индекс из первого поиска для описания поддиапазона во втором векторе.

Я вообще не хочу делать никаких медленных линейных манипуляций типа std::distance. Производительность имеет решающее значение.

Каков наилучший способ добиться этого?

заранее спасибо

Это похоже на XY-проблему, зачем вам RandomAccessIterator?

infinitezero 19.07.2024 12:20
std::lower_bound на std::vector вернет std::vector::iterator, то есть RandomAccessIterator...
Yksisarvinen 19.07.2024 12:21

Это похоже на то, что сказал @Yksisarvinen. ForwardIterator, который вы можете увидеть в разделе «Разное». документация просто означает, что это должен быть как минимум прямой итератор, передаваемый алгоритму. Алгоритм вернет итератор того же типа, который вы ему передаете.

Ted Lyngmo 19.07.2024 12:28

Кроме того, std::distance не является линейным для vector::iterator. Вместо этого он использует оператор - итератора. Для вектора v.begin() + index является итератором элемента по этому индексу, а iter - v.begin() возвращает индекс.

BoP 19.07.2024 12:41

@infinitezero Вы не можете выполнять двоичный поиск с чем-то другим, кроме RandomAccessIterstor.

Sneftel 20.07.2024 23:26
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как упоминалось в комментариях, вы можете просто использовать std::lower_bound с std::vector, чтобы получить RandomAccessIterator.

std::lower_bound вызывает свой параметр шаблона итератора ForwardIt, потому что итераторы first и last должны быть как минимум прямыми (и в этом случае возвращается прямой итератор).

Но тип возвращаемого итератора соответствует типу first и last (поскольку внутри это результат манипулирования ими для поиска в диапазоне).

Для std::vector они будут иметь тип std::vector::iterator, который является RandomAccessIterator, и возвращаемое значение тоже будет таким же.

Ответ принят как подходящий

И RandomAccessIterator, и ForwardIterator являются именованными требованиями, а не типами. RandomAccessIterator включает в себя ForwardIterator, т. е. он соответствует всем требованиям ForwardIterator, а также некоторым дополнительным.

По этой причине каждый тип, удовлетворяющий требованиям RandomAccessIterator, также удовлетворяет требованиям ForwardIterator.

std::lower_bound — шаблонная функция. Он принимает пару итераторов определенного типа и возвращает итератор того же типа. Требуется, чтобы тип итератора удовлетворял как минимум ForwardIterator. Стандарт называет параметр типа ForwardIterator, поскольку он определяет требования алгоритмов по именам параметров.

Если параметр шаблона алгоритма имеет имя ForwardIterator, ForwardIterator1 или ForwardIterator2, аргумент шаблона должен удовлетворять требованиям прямого итератора.

[algorithms.general]

Тип итератора, который вы получаете из std::vector, std::vector::iterator, должен удовлетворять RandomAccessIterator, и, следовательно, он удовлетворяет ForwardIterator.

Таким образом, вы можете передать пару std::vector::iterator в std::lower_bound и получить в результате std::vector::iterator.

Н.б. std::distance не является линейной манипуляцией, когда вы передаете ему тип, удовлетворяющий RandomAccessIterator:

Эффекты: Если InputIterator соответствует требованиям итератора произвольного доступа, возвращается (last - first); в противном случае возвращает количество приращений, необходимое для перехода от first к last.

[iterator.operations]

Каков наилучший способ добиться этого?

std::lower_bound. Технически стандарт не требует, чтобы реализации эффективно перемещались между элементами, но все основные из них требуют, чтобы им были присвоены RandomAccessIterators.

Я бы назвал их «именованными требованиями» или что-то в этом роде, чтобы избежать путаницы с реальными концепциями.

HolyBlackCat 19.07.2024 19:47

Другие вопросы по теме