我有一个简单的要求,我需要一个类型的地图。但是我需要最快的理论上可能的检索时间。
我使用了map和tr1中新提出的unordered_map 我发现至少在解析文件和创建地图时,通过在时间插入一个元素。
地图只花了2分钟,而unordered_map花了5分钟。
因为它将成为在Hadoop集群上执行的代码的一部分,并且将包含约1亿个条目,所以我需要尽可能少的检索时间。
另一个有用的信息: 目前正在插入的数据(键)是从1,2,......到~1,000万的整数范围。
我还可以强制用户指定最大值并使用上面的顺序,这会显着影响我的实现吗? (我听说地图是基于rb树的,按顺序插入会导致更好的性能(或最差?))
这是代码
map<int,int> Label // this is being changed to unordered_map
fstream LabelFile("Labels.txt");
// Creating the map from the Label.txt
if (LabelFile.is_open())
{
while (! LabelFile.eof() )
{
getline (LabelFile,inputLine);
try
{
curnode=inputLine.substr(0,inputLine.find_first_of("\t"));
nodelabel=inputLine.substr(inputLine.find_first_of("\t")+1,inputLine.size()-1);
Label[atoi(curnode.c_str())]=atoi(nodelabel.c_str());
}
catch(char* strerr)
{
failed=true;
break;
}
}
LabelFile.close();
}
暂定解决方案:在审核了评论和答案之后,我相信动态C ++数组将是最佳选择,因为实现将使用密集键。感谢
答案 0 :(得分:10)
unordered_map的插入应为 O(1) ,检索应大致为 O(1) , (它本质上是一个哈希表)。
因此,您的时间安排 OFF ,或者您的实施或使用unordered_map存在错误。
您需要提供更多信息,以及您可能使用容器的方式。
根据n1836的第6.3节,给出了插入/回溯的复杂性:
您应该考虑的一个问题是,您的实施可能需要不断 重新发布 结构,正如您所说 100mil + items 。在这种情况下,当实例化容器时,如果您已经大致了解将多少“唯一”元素插入到容器中,您可以将其作为参数传递给构造函数,容器将相应地用适当大小的桶表进行实例化。
答案 1 :(得分:2)
加载unordered_map的额外时间是由于动态数组调整大小。调整大小的时间表是当表超过其加载因子时每个单元的数量加倍。因此,从空表中,期望整个数据表的O(lg n)个副本。您可以通过预先调整哈希表的大小来消除这些额外的副本。具体地
Label.reserve(expected_number_of_entries / Label.max_load_factor());
除以max_load_factor是为了考虑哈希表运行所必需的空单元格。
答案 2 :(得分:1)
unordered_map(至少在大多数实现中)提供快速检索,但与map相比插入速度相对较差。当数据随机排序时,树通常处于最佳状态,而当数据被排序时,树处于最差状态(您不断插入树的一端,增加重新平衡的频率)。
鉴于它总共有大约1000万个条目,你可以只分配一个足够大的数组,并获得非常快速的查找 - 假设有足够的物理内存而不会引起颠簸,但这并不是现代的大量内存标准。
编辑:是的,矢量基本上是一个动态数组。
Edit2:您添加了一些问题的代码。您的while (! LabelFile.eof() )
已损坏。您通常希望执行while (LabelFile >> inputdata)
之类的操作。你也有点低效地阅读数据 - 你显然期望的是两个由标签分隔的数字。既然如此,我会写出类似的循环:
while (LabelFile >> node >> label)
Label[node] = label;