我应该用

std::sort(numbers.begin(), numbers.end(), std::greater<int>());

or

std::sort(numbers.rbegin(), numbers.rend());   // note: reverse iterators

按降序对向量排序?这两种方法有什么优点或缺点吗?


当前回答

您可以使用第一个方法,也可以尝试下面同样有效的代码

sort(&a[0], &a[n], greater<int>());

其他回答

这个呢?

std::sort(numbers.begin(), numbers.end());
std::reverse(numbers.begin(), numbers.end());

事实上,第一个不是个好主意。可以用第二个,也可以用这个:

struct greater
{
    template<class T>
    bool operator()(T const &a, T const &b) const { return a > b; }
};

std::sort(numbers.begin(), numbers.end(), greater());

这样,当有人决定数字应该保持long或long long而不是int时,您的代码就不会无声地中断。

根据我的机器,对[1..]使用第一种方法大约需要4秒,而使用第二种方法大约需要两倍的时间。这显然说明了一些问题,但我也不明白为什么。我只是觉得这会有帮助。

这里也报道了同样的事情。

正如Xeo所说,用-O3,它们用相同的时间完成。

博士TL;

使用任何。它们几乎一样。

无聊的答案

和往常一样,有利有弊。

使用std:: reverse_iterator:

当你在排序自定义类型,而你不想实现 操作符> () 当你懒得输入std::greater<int>()

在以下情况使用std::greater:

当你想要更显式的代码时 当您希望避免使用模糊的反向迭代器时

至于性能,两种方法的效率是一样的。我尝试了以下基准:

#include <algorithm>
#include <chrono>
#include <iostream>
#include <fstream>
#include <vector>

using namespace std::chrono;

/* 64 Megabytes. */
#define VECTOR_SIZE (((1 << 20) * 64) / sizeof(int))
/* Number of elements to sort. */
#define SORT_SIZE 100000

int main(int argc, char **argv) {
    std::vector<int> vec;
    vec.resize(VECTOR_SIZE);

    /* We generate more data here, so the first SORT_SIZE elements are evicted
       from the cache. */
    std::ifstream urandom("/dev/urandom", std::ios::in | std::ifstream::binary);
    urandom.read((char*)vec.data(), vec.size() * sizeof(int));
    urandom.close();

    auto start = steady_clock::now();
#if USE_REVERSE_ITER
    auto it_rbegin = vec.rend() - SORT_SIZE;
    std::sort(it_rbegin, vec.rend());
#else
    auto it_end = vec.begin() + SORT_SIZE;
    std::sort(vec.begin(), it_end, std::greater<int>());
#endif
    auto stop = steady_clock::now();

    std::cout << "Sorting time: "
          << duration_cast<microseconds>(stop - start).count()
          << "us" << std::endl;
    return 0;
}

使用以下命令行:

g++ -g -DUSE_REVERSE_ITER=0 -std=c++11 -O3 main.cpp \
    && valgrind --cachegrind-out-file=cachegrind.out --tool=cachegrind ./a.out \
    && cg_annotate cachegrind.out
g++ -g -DUSE_REVERSE_ITER=1 -std=c++11 -O3 main.cpp \
    && valgrind --cachegrind-out-file=cachegrind.out --tool=cachegrind ./a.out \
    && cg_annotate cachegrind.out

std::更大的演示 std:: reverse_iterator演示

时间是一样的。Valgrind报告了相同数量的缓存丢失。

使用第一个:

std::sort(numbers.begin(), numbers.end(), std::greater<int>());

它清楚地显示了正在发生的事情——将rbegin误读为begin的可能性更小,甚至带有注释。它清晰易读,这正是你想要的。

另外,考虑到反向迭代器的性质,第二个迭代器的效率可能比第一个要低,尽管您必须对它进行分析以确定。