在C++中对范围(没有重复项)进行排序是 std::vector 和 std::sort 比 std::set 快

Sorting a range (with no duplicates) in C++, is std::vector and std::sort faster than std::set?

本文关键字:std 排序 vector set sort 范围 C++      更新时间:2023-10-16

我有一个双精度序列(没有重复(,我需要对它们进行排序。填充vector然后sort它是否比insert set中的值更快?

如果不了解标准库的实现(并且不了解程序将运行的硬件(,而只是通过C++标准提供的信息,是否可以回答这个问题?

#include <vector>
#include <set>
#include <algorithm>
#include <random>
#include <iostream>
std::uniform_real_distribution<double> unif(0,10000);
std::default_random_engine re;
int main()
{
    std::vector< double > v;
    std::set< double > s;
    std::vector< double > r;
    size_t sz = 10;
    for(size_t i = 0; i < sz; i++) {
        r.push_back( unif(re) );
    }
    for(size_t i = 0; i < sz; i++) {
        v.push_back(r[i]);
    }
    std::sort(v.begin(),v.end());
    for(size_t i = 0; i < sz; i++) {
        s.insert(r[i]);
    }
    return 0;
}

从C++标准来看,我们只能说它们都具有相同的渐近复杂度(O(n*log(n))(。

对于无法有效移动或交换的大型对象,该集合可能会更快,因为对象不需要多次移动。对于小对象,矢量可能更快,因为对它进行排序不涉及指针更新和较少的间接性。

在任何给定的情况下,哪个更快只能通过测量(或对实施和目标平台的全面了解(来确定。

由于数据缓存因素,矢量的使用可能更快,因为操作的数据将位于更连贯的内存区域中(可能(。

矢量每个值的内存开销也更少。

如果可以,请在插入数据之前保留矢量大小,以最大程度地减少用值填充矢量时的工作量。

就复杂度而言,两者应该是相同的,即nlog(n(。

答案并非微不足道。如果您的软件中有 2 个主要部分:第一次设置、第二次查找和查找设置使用得更多:排序vector可能会更快,原因有 2 个:

  1. lower_bound <algorithm>函数比通常的树实现<set>更快,
  2. std::vector内存分配的堆页较少,因此在查找元素时,页面错误将较少。

如果用法混合,或者查找不多于设置,则<set>会更快。更多信息:Scott Meyers:Effective STL,第23项。

既然你说在一个范围内排序,你可以使用partial_sort而不是对整个集合进行排序。
如果我们不想打扰现有集合,并希望拥有一个具有排序数据且没有重复项的新集合,那么std::set为我们提供了一个直接的解决方案。

#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
    int arr[] = { 1, 3, 4, 1, 6, 7, 9, 6 , 3, 4, 9 };
    vector<int> ints ( arr, end(arr));
    const int ulimit = 5;
    auto last = ints.begin();
    advance(last, ulimit);
    set<int> sortedset;
    sortedset.insert(ints.begin() , last);
    for_each(sortedset.begin(), sortedset.end(), [](int x) { cout << x << "n"; });
}