Вход/Регистрация
Эффективное использование STL
вернуться

Мейерс Скотт

Шрифт:

 lp.end, // объектом lр, предшествующим

 newPerson, // или эквивалентным newPerson

 PersonNameLess), newPerson);

Приведенное решение работоспособно и достаточно удобно, но не стройте иллюзий насчет того, что оно каким-то волшебным способом обеспечивает поиск точки вставки в контейнер

list
с логарифмической сложностью. Как объясняется в совете 34, при работе с
list
поиск занимает линейное время, но при этом выполняется логарифмическое количество сравнений.

До настоящего момента рассматривался только случай, когда поиск осуществляется в интервале, определяемом парой итераторов. Довольно часто работать приходится со всем контейнером вместо интервала. В этом случае необходимо различать последовательные и ассоциативные контейнеры. Для стандартных последовательных контейнеров (

vector
,
string
,
deque
и
list
) достаточно следовать рекомендациям, изложенным ранее, используя начальный и конечный итераторы контейнера для определения интервала.

Со стандартными ассоциативными контейнерами (

set
,
multiset
,
map
,
multimap
) дело обстоит иначе. В них предусмотрены функции поиска, которые по своим возможностям обычно превосходят алгоритмы STL Превосходство функций контейнеров перед алгоритмами подробно рассматривается в совете 44; если говорить кратко — они быстрее работают и ведут себя более последовательно. К счастью, имена функций обычно совпадают с именами соответствующих алгоритмов, поэтому там, где речь идет об алгоритмах
count
,
find
,
lower_bound
,
upper_bound
и
equal_range
, при поиске в ассоциативных контейнерах вместо них достаточно выбрать одноименную функцию. К сожалению, для алгоритма
binary_search
парной функции не существует. Чтобы проверить наличие значения в контейнере
set
или
map
, воспользуйтесь идиоматической ролью
count
как условия проверки:

set<Widget> s; // Создать множество, заполнить данными

…

Widget w; // Искомое значение

…

if (s.count(w)) { // Существует значение, эквивалентное w

 …

} else {

 … // Эквивалентное значение не существует

}

При проверке присутствия значений в контейнерах

multiset
или
multimap
функция
find
обычно превосходит
count
, поскольку она останавливается при обнаружении первого объекта с искомым значением, а функция count в худшем случае просматривает все элементы контейнера.

Тем не менее при подсчете объектов в ассоциативных контейнерах

count
надежно занимает свою нишу. В частности, вызов
count
предпочтительнее вызова
equal_range
с последующим применением
distance
к полученным итераторам. Во-первых, само название функции подсказывает ее смысл — слово
count
означает «подсчет». Во-вторых,
count
упрощает работу программиста, поскольку ему не приходится создавать пару и передавать ее компоненты при вызове
distance
. В-третьих,
count
работает чуть быстрее.

Попробуем подвести итог всему, о чем говорилось в настоящем совете. Информация собрана в следующей таблице.

Алгоритм Функция контейнера
Что вы хотите узнать Несортированный интервал Сортированный интервал Для set и map Для multiset и multimap
Присутствует ли заданное значение? find binary_search count find
Присутствует ли заданное значение? И если присутствует, то где находится первый объект с этим значением? find equal_range find find или lower_bound (см. ранее)
Где находится первый объект со значением, не предшествующим заданному? find_if lower_bound lower_bound lower_bound
Где находится первый объект со значением, следующим после заданного? find_if upper_bound upper_bound upper_bound
Сколько объектов имеют заданное значение? count equal_range count count
Где находятся все объекты с заданным значением? equal_range equal_range equal_range find (итеративный вызов)

Несколько странно выгладит частое присутствие

equal_range
в столбце, относящемся к сортированным интервалам. Оно связано с особой ролью проверки эквивалентности при поиске. Использование
lower_bound
и
upper_bound
чревато ошибочной проверкой равенства, а при использовании
equal_range
более естественно выглядит проверка эквивалентности. Во второй строке предпочтение отдается
equal_range
еще по одной причине:
equal_range
работает с логарифмическим временем, а вызов
find
связан с линейными затратами времени.

  • Читать дальше
  • 1
  • ...
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: