возвращает итератор, указывающий на первый подходящий элемент (если таковой имеется) или на позицию, где он мог бы быть (если такого элемента нет); последнее полезно для поиска верного места для вставки новых значений в отсортированную последовательность. Алгоритм
upper_bound
возвращает итератор, указывающий на элемент, следующий за последним найденным элементом (если таковой имеется), т.е. на позицию, куда можно добавить следующий эквивалентный элемент; это полезно при поиске правильного места для вставки новых значений в отсортированную последовательность, чтобы поддерживать упорядоченность,
при которой равные элементы располагаются в последовательности в порядке их вставки.
Для сортированных диапазонов в качестве быстрой версии
count(first, last, value);
лучше использовать пару вызовов:
p = equal_range(first, last, value);
distance(p.first, p.second);
При поиске в ассоциативном контейнере лучше использовать вместо алгоритмов-не членов функции-члены с тем же именем. Функции-члены обычно более эффективны; например, функция-член
count
выполняется за логарифмическое время (так что, кстати, нет никаких оснований заменять ее вызовом
equal_range
с последующим distance, что имеет смысл для функции count, не являющейся членом).
При сортировке вы должны четко понимать, как работает каждый из сортирующих алгоритмов, и использовать наиболее дешевый среди тех, которые пригодны для решения вашей задачи.
Обсуждение
Вам не всегда требуется полный
sort
; обычно надо меньшее, и весьма редко — большее. В общем случае стандартные алгоритмы сортировки располагаются от наиболее дешевых до наиболее дорогих в следующем порядке:
partition
,
stable_partition
,
nth_element
,
partial_sort
(и его вариант
partial_sort_copy
),
sort
и
stable_sort
. Используйте наименее дорогой из алгоритмов, которые выполняют необходимую вам работу; применение излишне мощного алгоритма — расточительство.
Время работы алгоритмов
partition
,
stable_partition
и
nth_element
— линейное, что является очень хорошим показателем.
Алгоритмы
nth_element
,
partial_sort
,
sort
и
stable_sort
требуют итераторы произвольного доступа. Вы не можете использовать их при наличии только двунаправленных итераторов (например,
list<T>::iterator
). Если вам нужны данные алгоритмы, но у вас нет итераторов произвольного доступа, вы можете воспользоваться идиомой индексного контейнера: создайте контейнер, поддерживающий итераторы произвольного доступа (например, vector), в котором будут храниться итераторы, указывающие на элементы интересующего вас диапазона, и затем примените к нему более мощный алгоритм с использованием разыменовывающей версии вашего предиката (в которой перед обычным сравнением выполняется разыменование итераторов).
Версии
stable_
… следует
применять только тогда, когда вам необходимо сохранить относительный порядок одинаковых элементов. Заметим, что алгоритмы
partial_sort
и
nth_element
не являются устойчивыми (т.е. они не оставляют одинаковые элементы в том же относительном порядке, в котором они находились до сортировки), и у них нет стандартизированных устойчивых версий. Если вам все же требуется сохранение относительной упорядоченности элементов, вероятно, вам надо использовать
stable_sort
.
Само собой разумеется, не следует прибегать ни к каким алгоритмам сортировки, если вы можете обойтись без них. Если вы пользуетесь стандартным ассоциативным контейнером (
set
/
multiset
или
map
/
multimap
) или адаптером
priority_queue
, и вам требуется только один порядок сортировки, то не забывайте, что элементы в этих контейнерах всегда находятся в отсортированном виде.
Примеры
Пример 1.
partition
. Если вам надо разделить весь диапазон на две группы (группа элементов, удовлетворяющих предикату, за которыми следует группа элементов, предикату не удовлетворяющих), то для этого достаточно воспользоваться алгоритмом
partition
. Это все, что вам надо, чтобы ответить на вопросы наподобие приведенных далее.
• Кто из студентов имеет средний бал не ниже 4.5? Для ответа на этот вопрос можно воспользоваться вызовом
вернет итератор, указывающий на первый товар, вес которого не ниже 10 кг.
Пример 2.
nth_element
. Алгоритм
nth_element
можно использовать для того, чтобы получить один элемент в корректной n-й позиции, в которой он бы находился при полной сортировке всего диапазона, при этом все прочие элементы корректно располагаются до или после этого n-го элемента. Этого достаточно, чтобы ответить на вопросы наподобие следующих.
помещает 20 наилучших покупателей в начало контейнера.
• Какое изделие имеет медианное значение качества в данном наборе? Искомый элемент находится в средней позиции отсортированного диапазона. Для его поиска достаточно вызова
• У какого изделия уровень качества находится на 75-м перцентиле? Искомый элемент находится в позиции, отстоящей на 25% от начала отсортированного диапазона. Для его поиска достаточно вызова