Мне нужен алгоритм двоичного поиска, совместимый с контейнерами C ++ STL, что-то вроде заголовка std::binary_search
стандартной библиотеки <algorithm>
, но мне нужно, чтобы он возвращал итератор, указывающий на результат, а не простое логическое значение, сообщающее мне, существует ли элемент.
(Кстати, о чем, черт возьми, думал стандартный комитет, когда определяли API для binary_search ?!)
Меня больше всего беспокоит то, что мне нужна скорость двоичного поиска, поэтому, хотя я могу найти данные с помощью других алгоритмов, как указано ниже, я хочу воспользоваться тем фактом, что мои данные отсортированы, чтобы получить преимущества двоичного поиск, а не линейный поиск.
до сих пор lower_bound
и upper_bound
терпеть неудачу, если данные отсутствуют:
//lousy pseudo code
vector(1,2,3,4,6,7,8,9,0) //notice no 5
iter = lower_bound_or_upper_bound(start,end,5)
iter != 5 && iter !=end //not returning end as usual, instead it'll return 4 or 6
Примечание. Я также могу использовать алгоритм, который не принадлежит пространству имен std, если он совместим с контейнерами. Как, скажем, boost::binary_search
.
источник
Ответы:
Таких функций нет, но вы можете написать простую, используя
std::lower_bound
,std::upper_bound
илиstd::equal_range
.Простая реализация могла бы быть
Другое решение - использовать a
std::set
, который гарантирует упорядочение элементов и предоставляет метод,iterator find(T key)
который возвращает итератор для данного элемента. Однако ваши требования могут быть несовместимы с использованием набора (например, если вам нужно сохранить один и тот же элемент несколько раз).источник
*i == val
! Скорее использовать!(val < *i)
. Причина в том, чтоlower_bound
using<
, not==
(т.е.T
даже не требуется, чтобы быть сопоставимым по равенству). (См. « Эффективный STL» Скотта Мейерса для объяснения разницы между равенством и эквивалентностью .)end
. Диапазоны в стандартной библиотеке C ++ представлены с полуоткрытыми интервалами: конечный итератор «указывает» после последнего элемента. Таким образом, он может быть возвращен алгоритмами, чтобы указать, что значение не найдено.Вы должны взглянуть на
std::equal_range
. Он вернет пару итераторов в диапазон всех результатов.источник
Их множество:
http://www.sgi.com/tech/stl/table_of_contents.html
Ищи:
Отдельно отметим:
Вероятно, они думали, что поиск в контейнерах может дать более одного результата. Но в странном случае, когда вам просто нужно проверить наличие, оптимизированная версия также будет хороша.
источник
Если std :: lower_bound слишком низкоуровневый для вашего вкуса, вы можете проверить boost :: container :: flat_multiset . Это прямая замена std :: multiset, реализованная как отсортированный вектор с использованием двоичного поиска.
источник
Самая короткая реализация, интересно, почему ее нет в стандартной библиотеке:
С https://en.cppreference.com/w/cpp/algorithm/lower_bound
источник
Отметьте эту функцию, qBinaryFind :
Функция включена в
<QtAlgorithms>
заголовок, который является частью библиотеки Qt .источник
std :: lower_bound () :)
источник
Пример: Рассмотрим массив, A = [1,2,3,4,5,6,7,8,9] Предположим, вы хотите найти индекс 3 Изначально start = 0 и end = 9-1 = 8 Теперь , так как start <= end; mid = 4; (array [mid], который равен 5)! = 3 Теперь 3 лежит слева от mid, поскольку он меньше 5. Следовательно, мы ищем только левую часть массива. Следовательно, теперь start = 0 и end = 3; mid = 2. Так как array [mid] == 3, значит, мы получили число, которое искали. Следовательно, мы возвращаем его индекс, равный mid.
источник
Решение, возвращающее позицию внутри диапазона, может быть таким, используя только операции с итераторами (оно должно работать, даже если итератор не арифметический):
источник