自从我最近遇到这个问题以来,我做了一些测量。
我有一张大地图,有很多数据,很少插入数据,99% 的时间只是使用引用就地访问和修改。但是,这些数据最终必须保存到磁盘并重新加载。像“使用无序地图”这样的解决方案似乎是一种廉价的快速错误方法,有序地图对我来说是正确的方法,因为数据是有序的。唯一的问题是从文件加载。
我想知道这个操作的真正成本是多少以及如何加快它,所以我测量了:
// Example program
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <time.h>
std::vector<int> amount = {100, 1000, 10000, 100000, 1000000, 5000000};
int main()
{
for(int j=0; j<amount.size(); j++)
{
clock_t tStart = clock();
std::map<int,int> mymap;
for(int i=0; i<amount[j]; i++){
mymap[i] = i;
}
printf("Time taken []: %.2fs\n", (double)(clock() - tStart));
}
for(int j=0; j<amount.size(); j++)
{
clock_t tStart = clock();
std::map<int,int> mymap;
mymap[0] = 0;
auto it = mymap.begin();
for(int i=1; i<amount[j]; i++){
it = mymap.insert(it, std::pair<int,int>(i,i));
}
printf("Time taken insert end()-1: %.2fns\n", (double)(clock() - tStart));
}
for(int j=0; j<amount.size(); j++)
{
clock_t tStart = clock();
std::map<int,int> mymap;
for(int i=1; i<amount[j]; i++){
mymap.insert(mymap.end(), std::pair<int,int>(i,i));
}
printf("Time taken insert end(): %.2fns\n", (double)(clock() - tStart));
}
for(int j=0; j<amount.size(); j++)
{
clock_t tStart = clock();
std::map<int,int> mymap;
for(int i=0; i<amount[j]; i++){
mymap.insert(mymap.begin(), std::pair<int,int>(i,i));
}
printf("Time taken insert begin(): %.2fs\n", (double)(clock() - tStart));
}
return 0;
}
结果:
Time in ns
N end()-1 end() begin() []
100 12 8 22 12
1000 77 54 188 97
10000 763 532 2550 1174
100000 7609 6042 23612 17164
1000000 75561 62048 270476 272099
5000000 362463 306412 1827807 1687904
概括:
是的,有收获,巨大的收获,没有任何真正的缺点。对数据进行排序时,比无序地图要好得多,对于将地图保存到文件并重新创建它的情况非常有用。
无论元素数量如何,如果提示正确,插入时间都是相同的。因此,无需重复使用散列无序映射来获得恒定时间。
最坏的情况是,如果您的提示是最坏的提示,您可能会丢失一些提示。我认为在没有提示的情况下进行插入没有任何意义,特别是如果您知道数据将插入的位置。大多数时候你都会这样做。