簡體   English   中英

按降序對矢量進行排序

[英]Sorting a vector in descending order

我應該用嗎?

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

要么

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

按降序對矢量進行排序? 一種方法或另一種方法有任何好處或缺點嗎?

實際上,第一個是個壞主意。 使用第二個 ,或者:

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應該持有多long或多long long而不是int時,你的代碼不會默默地破壞。

使用第一個:

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

這是明確的是怎么回事的-誤讀的機會較少rbegin作為begin ,即使有意見。 它清晰可讀,正是您想要的。

此外,第二個可能效率低於第一個給定反向迭代器的性質,盡管你必須對其進行分析以確定。

使用c ++ 14,您可以這樣做:

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

那這個呢?

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

您可以使用Lambda函數代替Mehrdad提出的仿函數。

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

根據我的機器,使用第一種方法對[1..3000000]的long long矢量進行排序大約需要4秒,而使用第二種方法需要大約兩倍的時間。 顯然,這說了些什么,但我也不明白為什么。 試想這會有所幫助。

同樣的事情這報道。

正如Xeo所說,他們使用-O3大約在同一時間完成。

第一種方法是:

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

您可以使用第一種方法,因為它比第二種方法獲得更高的效率。
第一種方法的時間復雜度小於第二種方法。

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

您可以使用第一個或嘗試下面同樣有效的代碼

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

我不認為你應該使用問題中的任何一種方法,因為它們都令人困惑,而第二種方法就像Mehrdad所暗示的那樣脆弱。

我主張以下內容,因為它看起來像一個標准的庫函數,並明確其意圖:

#include <iterator>

template <class RandomIt>
void reverse_sort(RandomIt first, RandomIt last)
{
    std::sort(first, last, 
        std::greater<typename std::iterator_traits<RandomIt>::value_type>());
}

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 std::reverse_iterator demo std::reverse_iterator演示

時間是一樣的。 Valgrind報告了相同數量的緩存未命中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM