Должен ли я использовать
std::sort(numbers.begin(), numbers.end(), std::greater<int>());
или
std::sort(numbers.rbegin(), numbers.rend()); // note: reverse iterators
отсортировать вектор в порядке убывания? Есть ли какие-либо преимущества или недостатки с одним подходом или другим?
reverse_iterator
.std::sort(b, e);
ставит минимум наb
(в нашем случаеrbegin
, так что последний элемент) и максимум наe
(в нашем случаеrend
, так что первый элемент).Ответы:
На самом деле, первая - плохая идея. Используйте либо второй , либо этот:
Таким образом, ваш код не будет молча ломаться, когда кто-то решит, что он
numbers
должен хранитьсяlong
илиlong long
вместоint
.источник
greater
чем другие?rbegin
иrend
были сделаны для конкретной цели.std::greater<typename decltype(numbers)::value_type>()
или что-то?std::greater<>()
начиная с C ++ 14.Используйте первое:
Это явно что происходит - меньше шансов искажения ,
rbegin
какbegin
, даже с комментарием. Это ясно и понятно, что именно то, что вы хотите.Кроме того, второй может быть менее эффективным, чем первый, учитывая природу обратных итераторов, хотя вам, конечно, придется профилировать его.
источник
С C ++ 14 вы можете сделать это:
источник
Как насчет этого?
источник
=
и+
просто означает значение∈
и удобство∪
. В таком случаеO(n*log(n)) + O(n)
это удобное обозначение, дляO(n*log(n)) ∪ O(n)
которого так же, какO(n*log(n))
. Слово «вычисление» является хорошим предложением, и вы правы в отношении тона.Вместо функтора, как предложил Mehrdad, вы можете использовать функцию Lambda.
источник
Согласно моей машине, сортировка
long long
вектора [1..3000000] с использованием первого метода занимает около 4 секунд, в то время как использование второго занимает примерно вдвое больше времени. Это говорит о чем-то, очевидно, но я тоже не понимаю почему. Просто думаю, что это было бы полезно.То же самое сообщается здесь .
Как сказал Xeo, с ними
-O3
они используют примерно одно и то же время, чтобы закончить.источник
reverse_iterator
операции не были встроены, и, учитывая, что они являются просто оберткой вокруг реальных итераторов, неудивительно, что они удваивают время без вставки.base()
Функция состоит, например , возвращает обернутую итератор.std::vector<>::reverse_iterator
реализуется с точки зренияstd::reverse_iterator<>
. Необычный; сегодня я узнал. :-PВы можете использовать первый подход, потому что получаете больше эффективности, чем второй.
Время сложность первого подхода меньше, чем второй.
источник
источник
TL; DR
Используйте любой. Они почти одинаковые.
Скучный ответ
Как обычно, есть плюсы и минусы.
Используйте
std::reverse_iterator
:operator>()
std::greater<int>()
Используйте
std::greater
когда:Что касается производительности, оба метода одинаково эффективны. Я попробовал следующий тест:
С этой командной строкой:
std::greater
demostd::reverse_iterator
demoСроки такие же. Valgrind сообщает о том же количестве пропусков кеша.
источник
Я не думаю, что вы должны использовать ни один из методов в вопросе, поскольку они оба сбивают с толку, а второй является хрупким, как предполагает Мерадад.
Я бы выступил за следующее, так как оно выглядит как стандартная библиотечная функция и проясняет ее намерения:
источник
std::greater
компаратора ....Вы можете использовать первый или попробовать приведенный ниже код, который одинаково эффективен
источник