我有一系列数字(未分类,没有重复)与目标进行排序。
方法1:插入向量。 O(n),使用排序算法和排序。 O(nlogn)
方法2:插入集合。 O(nlogn)
哪种方法会更快?
我觉得set会更快,因为vector中的每个插入都必须分配 完成数组元素并复制它然后删除它可能是昂贵的。但是我在网上阅读了大部分地方的矢量已经过了。
任何人都可以建议我使用正确的逻辑哪一个更快?
编辑: 如果我们事先不知道哪个元素会更快设置或向量 (对于两个元素都没有,并且元素的数量很大? 注意:如果没有元素是大的设置似乎是更好的选择,但它对小也有好处吗?不知道)
答案 0 :(得分:4)
如果您事先了解了许多要素,您可以reserve()
向量中的空格以避免重新分配,使第一选择非常有趣(快速插入,单一的)。
如果您需要执行一次,请转到std::vector<>
。如果稍后在程序中发生其他插入,则std::set<>
可能会更有趣。
如果您事先不知道预期的尺寸,则可能会对矢量进行重新分配,std::set<>
是一个不错的选择(更好的理论平均复杂度) )。
O(n)+ O(n * log(n))对于 vs O(n * log(n))的集合
std::vector
无论如何,分析这两种解决方案总是一种很好的做法,实际结果将取决于输入的初始排序状态(以及其他内容),以及每个容器的实施质量。
注意:强>
std::set
有一个更大的记忆足迹,如果它对你很重要。答案 1 :(得分:1)
这取决于您的使用案例。
设置:
+快速数据插入O(logn)
+您无需关心排序
- 由于 set 是作为树实现的,因此每个元素都有内存开销。
-Data可以分布在内存堆中,因此CPU缓存效果不佳。
vector :
+数据包含在连续的内存块中。所以,你的CPU缓存更好。
+您的搜索相同O(logn)
+你可以
reserve
内存。- 你需要在每次改变后进行排序。
所以,如果你有很多元素并且做了一次插入,很多搜索&#34;,我更喜欢 vector 。如果您进行了许多插入/搜索查询,最好坚持使用设置。
用O()术语思考我说向量插入成本是O(nlogn),但是在所有插入之后可以调用一次。 设置插入成本为O(logn)并调用每个插入。因此,如果您需要在向量排序后进行插入,您将为向量支付num_insertions*O(nlogn)
,为设置支付O(log (n+num_insertions))
,这实际上更便宜。< / p>
答案 2 :(得分:1)
我以为我会使用分析器来研究这个问题。我的代码:
//g++ -std=c++11 -Wall vectorvsset.cpp -g -pg -o vectorvsset
#include <time.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
void GenRandom(vector<int32_t> &original)
{
original.clear();
for(size_t i=0; i<10000; i++)
original.push_back(rand());
}
void TestSet(const vector<int32_t> &original)
{
set<int32_t> testset;
testset.insert(original.begin(), original.end());
}
void TestVector(const vector<int32_t> &original)
{
vector<int32_t> testvec;
testvec.insert(testvec.end(), original.begin(), original.end());
sort(testvec.begin(), testvec.end());
}
void TestVectorConvertToSet(const vector<int32_t> &original)
{
vector<int32_t> testvec;
testvec.insert(testvec.end(), original.begin(), original.end());
sort(testvec.begin(), testvec.end());
std::set<int32_t> testsec(testvec.begin(), testvec.end());
}
int main()
{
srand(time(NULL));
cout << "RAND_MAX " << RAND_MAX << endl;
vector<int32_t> original;
for(size_t i=0; i<100; i++)
{
GenRandom(original);
TestSet(original);
TestVector(original);
TestVectorConvertToSet(original);
}
return 0;
}
在g ++上使用gprof(Ubuntu 5.4.0-6ubuntu1~16.04.4)5.4.0 20160609我的(缩写)结果是:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
0.00 1.42 0.00 100 0.00 3.36 TestVector(std::vector<int, std::allocator<int> > const&)
0.00 1.42 0.00 100 0.00 6.86 TestVectorConvertToSet(std::vector<int, std::allocator<int> > const&)
0.00 1.42 0.00 100 0.00 3.57 TestSet(std::vector<int, std::allocator<int> > const&)
因此使用矢量更快,但差别不大。