c ++中map和unordered_map之间的性能差异

时间:2010-02-28 06:02:17

标签: c++ data-structures stl tr1

我有一个简单的要求,我需要一个类型的地图。但是我需要最快的理论上可能的检索时间。

我使用了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 ++数组将是最佳选择,因为实现将使用密集键。感谢

3 个答案:

答案 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;