9. Не зная численности населения города, а также не задействуя оператор ==, можно выполнить поиск только путем сравнения названия с содержимым вектора. Функция std::find_if
{
auto found_cologne (find_if(begin(c), end(c),
[] (const auto &item) {
return item.name == "Cologne";
}));
print_city(found_cologne);
}
10. Чтобы сделать операцию поиска чуть более выразительной, можно реализовать конструктор предикатов. Объект функции population_higher_than
{
auto population_more_than ([](unsigned i) {
return [=] (const city &item) {
return item.population > i;
};
});
auto found_large (find_if(begin(c), end(c),
population_more_than(2000000)));
print_city(found_large);
}
11. Использованные нами функции поиска проходят по контейнерам линейно. Поэтому они имеют коэффициент сложности
print
: const vector
auto print_int (opt_print(v));
12. Функция std::binary_search
bool contains_7 {binary_search(begin(v), end(v), 7)};
cout << contains_7 << '\n';
13. Чтобы получить искомые элементы, нужно задействовать другие функции STL. Одной из них является функция std::equal_range
1
до 10
, первый итератор указывает на значение 7
, поскольку это первый элемент, чье значение не меньше 7
. Второй итератор — на значение 8
, так как это первый элемент, значение которого больше 7
. При наличии в нашем диапазоне нескольких элементов 7
оба итератора представляли бы собой auto [lower_it, upper_it] (
equal_range(begin(v), end(v), 7));
print_int(lower_it);
print_int(upper_it);
14. Если нужно получить только один итератор, то можно воспользоваться функциями std::lower_bound
std::upper_bound
. Первая возвращает итератор на первый элемент, чье значение не меньше искомого, вторая — на первый элемент, чье значение больше искомого: print_int(lower_bound(begin(v), end(v), 7));
print_int(upper_bound(begin(v), end(v), 7));
}
15. Скомпилируем и запустим программу для подтверждения того, что наши предположения и результат ее работы совпадают:
$ ./finding_items
{Cologne, 1060000}
{Cologne, 1060000}
{Berlin, 3502000}
1
7
8
7
8
Как это работает
В этом примере мы использовали следующие алгоритмы поиска (табл. 5.3).
Все описанные функции в качестве необязательного дополнительного аргумента принимают пользовательские функции сравнения. Таким образом, операцию поиска можно изменять, что мы и сделали в этом примере.
Рассмотрим более подробно принцип работы std::equal_range
v = {0,1,2,3,4,5,6,7,7,7,8}
и мы вызываем метод equal_range(begin(v),end(v),7);
, чтобы выполнить бинарный поиск значения 7
. Функция equal_range возвращает пару итераторов, указывающих на нижнюю и верхнюю границы; они указывают на диапазон {7,7,7}
, поскольку в векторе содержится именно столько значений 7
. Для большей ясности взгляните на рис. 5.1.