按降序对矢量进行排序

时间:2012-01-26 20:47:03

标签: c++ sorting stl vector iterator

我应该使用

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

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

按降序对矢量进行排序?一种方法或另一种方法有任何好处或缺点吗?

11 个答案:

答案 0 :(得分:103)

实际上,第一个是个坏主意。使用第二个,或者:

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

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

这样,当有人决定numbers应该暂停longlong long而不是int时,您的代码就不会默默地破解。

答案 1 :(得分:62)

使用第一个:

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

明确表示正在发生的事情 - 将rbegin误读为begin的可能性更小,即使有评论也是如此。它清晰可读,正是您想要的。

此外,第二个可能效率低于第一个给定反向迭代器的性质,尽管你必须对它进行分析以确定。

答案 2 :(得分:50)

使用c ++ 14,您可以这样做:

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

答案 3 :(得分:25)

这个怎么样?

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

答案 4 :(得分:20)

而不是Mehrdad提出的仿函数,你可以使用Lambda函数。

sort(numbers.begin(), numbers.end(), [](const int a, const int b) {return a > b; });

答案 5 :(得分:15)

根据我的机器,使用第一种方法对[1..3000000]的long long向量进行排序大约需要4秒,而使用第二种方法需要大约两倍的时间。显然,这说了些什么,但我也不明白为什么。试想这会有所帮助。

同样的事情报道here

正如Xeo所说,-O3他们使用大约相同的时间来完成。

答案 6 :(得分:10)

  

第一种方法是:

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

您可以使用第一种方法,因为效率高于第二种方法 第一种方法的时间复杂度低于第二种方法。

答案 7 :(得分:8)

最短的方法是:

std::sort(v.rbegin(), v.rend());

答案 8 :(得分:5)

bool comp(int i, int j) { return i > j; }
sort(numbers.begin(), numbers.end(), comp);

答案 9 :(得分:1)

我认为你不应该使用问题中的任何一种方法,因为它们既令人困惑,又第二种方法就像Mehrdad所暗示的那样脆弱。

我会提倡以下内容,因为它看起来像一个标准的库函数,并且明确了它的意图:

class ItemAction implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            //In case the user has not modified the object
            Member member = (Member)box.getSelectedItem();
            //Just an example here
            if(member != null) {
                System.out.println(member.toString());
            }
        } catch(ClassCastException ex) {
            //In case the object has been modified
            String data = (String)box.getSelectedItem();
            //Apply first method here
        }

    }
}

答案 10 :(得分:1)

TL; DR

使用任何。它们几乎相同。

无聊的答案

和往常一样,各有利弊。

使用std::reverse_iterator

  • 在对自定义类型进行排序时,您不想实现 operator>()
  • 如果您懒得键​​入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::greater demo std::reverse_iterator demo

时间是相同的。 Valgrind报告了相同数量的高速缓存未命中。