Читать «Стандарты программирования на С++. 101 правило и рекомендация» онлайн - страница 136

Андрей Александреску

• Перечислите 20 лучших покупателей. Вызов nth_element(s.begin(), s.begin()+19, s.end(), SalesRating); помещает 20 наилучших покупателей в начало контейнера.

• Какое изделие имеет медианное значение качества в данном наборе? Искомый элемент находится в средней позиции отсортированного диапазона. Для его поиска достаточно вызова nth_element(run.begin(), run.begin() + run.size()/2, run.end(), itemQuality);.

• У какого изделия уровень качества находится на 75-м перцентиле? Искомый элемент находится в позиции, отстоящей на 25% от начала отсортированного диапазона. Для его поиска достаточно вызова nth_element(run.begin(), run.begin()+run.size()*.25, run.end(), ItemQuality);.

Пример 3. partial_sort. Алгоритм partial_sort выполняет те же действия, что и nth_element, но кроме того обеспечивает корректное отсортированное размещение всех элементов до n-го. Алгоритм partial_sort используется для ответов на вопросы, аналогичные вопросам для nth_element, но в которых требуется, чтобы все интересующие элементы были корректно отсортированы. Этот алгоритм — все, что вам надо для ответа, например, на вопрос: "Кто из участников занял первое, второе и третье места?" Ответ можно получить при помощи вызова partial_sort(contestants.begin(), contestants.begin()+3, contestants.end(), ScoreCompare);, после которого участники, занявшие три первые места, окажутся в корректном порядке в трех первых элементах контейнера, и не более того.

Исключения

Хотя обычно алгоритм partial_sort быстрее полной сортировки (так как должен выполнять меньшее количество работы), если вам надо отсортировать почти весь (или весь) диапазон, то в этой ситуации алгоритм sort может оказаться быстрее.

Ссылки

[Austern99] §13.1 • [Bentley00] §11 • [Josuttis99] §9.2.2 • [Meyers01] §31 • [Musser01] §5.4, §22.26 • [Stroustrup00] §17.1.4.1, §18.7

87. Делайте предикаты чистыми функциями

Резюме

Предикат представляет собой функциональный объект, который возвращает ответ да/нет, обычно в виде значения типа bool. Функция является "чистой" в математическом смысле, если ее результат зависит только от ее аргументов (обратите внимание — в данном случае термин "чистая" не имеет никакого отношения к чисто виртуальным функциям).

Не позволяйте предикатам сохранять или обращаться к состоянию так, чтобы это могло влиять на результат работы оператора operator(); при этом понятие состояния включает как данные-члены, так и глобальные состояния. Для предикатов желательно делать оператор operator() константной функцией-членом (см. рекомендацию 15).

Обсуждение

Алгоритмы создают неизвестное количество копий предикатов в неизвестные моменты времени и в неизвестном порядке, так что приходится полагаться на то, что все копии эквивалентны.

Именно поэтому вы отвечаете за то, чтобы все копии предикатов были эквивалентны; это означает, что все они должны быть чистыми функциями, результат работы которых полностью и однозначно определяется аргументами, передаваемыми оператору operator() и не зависит ни от каких иных факторов. При передаче одних и тех же аргументов предикат всегда должен возвращать одно и то же значение.