我哪种情况会比排序的std::><vector<std:std::p air<A,B>>更快?
I which situation will std::map<A,B> be faster than sorted std::vector<std::pair<A,B>>?
我在某些代码中使用了map
来存储有序数据。我发现对于巨大的地图,破坏可能需要一段时间。在我有的这段代码中,将map
替换为vector<pair>
将处理时间减少了 10000...
非常惊讶,我决定将map
表演与排序vector
或pair
进行比较。
我很惊讶,因为我找不到map
比pair
的排序vector
快的情况(随机填充并稍后排序(......一定有一些情况map
更快。否则提供这门课有什么意义?
这是我测试的内容:
测试一个,比较map
填充和销毁与vector
填充、排序(因为我想要一个分类容器(和销毁:
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <map>
#include <vector>
#include <algorithm>
int main(void)
{
clock_t tStart = clock();
{
std::map<float,int> myMap;
for ( int i = 0; i != 10000000; ++i )
{
myMap[ ((float)std::rand()) / RAND_MAX ] = i;
}
}
std::cout << "Time taken by map: " << ((double)(clock() - tStart)/CLOCKS_PER_SEC) << std::endl;
tStart = clock();
{
std::vector< std::pair<float,int> > myVect;
for ( int i = 0; i != 10000000; ++i )
{
myVect.push_back( std::make_pair( ((float)std::rand()) / RAND_MAX, i ) );
}
// sort the vector, as we want a sorted container:
std::sort( myVect.begin(), myVect.end() );
}
std::cout << "Time taken by vect: " << ((double)(clock() - tStart)/CLOCKS_PER_SEC) << std::endl;
return 0;
}
用g++ main.cpp -O3 -o main
编译并得到:
Time taken by map: 21.7142
Time taken by vect: 7.94725
map
慢了3倍...
然后,我说,"好吧,矢量填充和排序更快,但使用地图搜索会更快"......所以我测试了:
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <map>
#include <vector>
#include <algorithm>
int main(void)
{
clock_t tStart = clock();
{
std::map<float,int> myMap;
float middle = 0;
float last;
for ( int i = 0; i != 10000000; ++i )
{
last = ((float)std::rand()) / RAND_MAX;
myMap[ last ] = i;
if ( i == 5000000 )
middle = last; // element we will later search
}
std::cout << "Map created after " << ((double)(clock() - tStart)/CLOCKS_PER_SEC) << std::endl;
float sum = 0;
for ( int i = 0; i != 10; ++i )
sum += myMap[ last ]; // search it
std::cout << "Sum is " << sum << std::endl;
}
std::cout << "Time taken by map: " << ((double)(clock() - tStart)/CLOCKS_PER_SEC) << std::endl;
tStart = clock();
{
std::vector< std::pair<float,int> > myVect;
std::pair<float,int> middle;
std::pair<float,int> last;
for ( int i = 0; i != 10000000; ++i )
{
last = std::make_pair( ((float)std::rand()) / RAND_MAX, i );
myVect.push_back( last );
if ( i == 5000000 )
middle = last; // element we will later search
}
std::sort( myVect.begin(), myVect.end() );
std::cout << "Vector created after " << ((double)(clock() - tStart)/CLOCKS_PER_SEC) << std::endl;
float sum = 0;
for ( int i = 0; i != 10; ++i )
sum += (std::find( myVect.begin(), myVect.end(), last ))->second; // search it
std::cout << "Sum is " << sum << std::endl;
}
std::cout << "Time taken by vect: " << ((double)(clock() - tStart)/CLOCKS_PER_SEC) << std::endl;
return 0;
}
用g++ main.cpp -O3 -o main
编译并得到:
Map created after 19.5357
Sum is 1e+08
Time taken by map: 21.41
Vector created after 7.96388
Sum is 1e+08
Time taken by vect: 8.31741
使用vector
甚至搜索速度显然更快(使用 map
进行 10 次搜索几乎需要 2 秒,而使用 vector
只花了半秒钟(....
所以:
- 我错过了什么吗?
- 我的测试不正确/不准确吗?
map
只是要避免的课程,还是真的存在map
提供良好表现的情况?
通常,当您在查找中穿插大量插入和删除时,map
会更好。如果您构建一次数据结构,然后只执行查找,则排序vector
几乎肯定会更快,即使只是因为处理器缓存效应。由于向量中任意位置的插入和删除是 O(n( 而不是 O(log n(,因此这些将成为限制因素。
std::find
具有线性时间复杂度,而map
搜索具有log N复杂度。
当您发现一种算法比另一种算法快 100000 倍时,您应该怀疑!您的基准无效。
您需要比较现实的变体。可能,您的意思是将地图与二叉搜索进行比较。运行每个变体至少 1 秒的 CPU 时间,以便您可以实际比较结果。
当基准测试返回"0.00001 秒"所花费的时间时,您就处于时钟不准确的噪声中。这个数字没有任何意义。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- C 建造者Clang STD :: Sill,找不到超载的操作员&lt;
- 为什么STD :: MAP需要操作员&lt;以及我如何写一个
- std::vector::reserve(未知m),我知道m<<;N(通常)并且知道N
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- C++运算符<<调用::ostream而不是std::osttream
- 是std :: set&lt; std :: future&gt;不可能存在
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- BOOST ::变体无法解决运算符&lt;&lt;对于STD :: Ostream
- C++重载<<具有typedef'd std::vector
- 以x的倍数填充前导零,使用std::cout<<std::十六进制
- 错误:没有匹配'运算符<<"在'std::cout
- std::pair的默认构造函数<>将基本类型(int等)设置为零
- std::ostream&operator< & lt; (std:: ostream&压力,压力& &;val)
- 将std::endl传递给std::operator<<
- std::映射<>或std::vector<>在处理大型标志集时
- 重载& lt; & lt;使用命名空间std