C ++ std :: unordered_map复杂性

时间:2013-10-26 18:40:52

标签: c++ stl iteration time-complexity unordered-map

我在stackoverflow上已经阅读了很多关于unordered_map (c ++ 11) 时间复杂度的内容,但我还没有找到答案对于我的问题。

让我们假设按整数索引(例如):

插入/在函数处不断工作(平均时间),因此这个例子需要O(1)

std::unordered_map<int, int> mymap = {
            { 1, 1},
            { 100, 2},
            { 100000, 3 }
};

我很好奇的是迭代存储在地图中的所有(未排序的)值需要多长时间 - 例如

for ( auto it = mymap.begin(); it != mymap.end(); ++it ) { ... }

我可以假设每个存储的值只被访问一次(或两次或恒定次数)吗?这意味着迭代所有值都在N值映射O(N)中。另一种可能性是我的密钥{1,10,100000}的例子最多需要1000000次迭代(如果用数组表示)

是否还有其他容器,可以线性迭代并且不断地通过给定密钥访问值?

我真正需要的是(伪代码)

myStructure.add(key, value) // O(1)
value = myStructure.at(key) // O(1)
for (auto key : mySructure) {...} // O(1) for each key/value pair = O(N) for N values

std :: unordered_map是我需要的结构吗?

整数索引也足够,平均复杂度也很高。

3 个答案:

答案 0 :(得分:13)

无论它们是如何实现的,标准容器都提供满足迭代器要求的迭代器。递增迭代器需要是恒定时间,因此遍历任何标准容器的所有元素都是O(N)。

答案 1 :(得分:3)

有一些不同的方法可以实现哈希表,如果你感兴趣,我建议你阅读更多关于这些的方法,但主要的两个是通过链接和开放寻址。

在第一种情况下,您有一系列链接列表。数组中的每个条目都可以为空,哈希表中的每个项都位于某个存储桶中。因此,迭代沿着数组向下走,并沿着它中的每个非空列表向下走。显然是O(N),但根据链表本身的分配方式,可能会非常低效。

在第二种情况下,你只有一个非常大的数组,它将有很多空插槽。在这里,迭代再次显然是线性的,但如果表大部分为空(这应该用于查找目的),则效率可能很低,因为实际存在的元素将位于不同的高速缓存行中。

无论哪种方式,你都会进行线性迭代,而你将完全触及每个元素一次。请注意,std::map也是如此,迭代在那里也是线性的。但是在地图的情况下,迭代肯定远没有迭代矢量的效率,所以请记住这一点。如果您的用例涉及要求快速查找和快速迭代,如果您预先插入所有元素并且永不擦除,那么实际上同时拥有地图和矢量可能会好得多。占用额外的空间以增加性能。

答案 2 :(得分:3)

所有标准容器的复杂性保证在C++ Standard中指定。

std::unordered_map元素访问和元素插入的平均复杂度O(1)O(N)最差情况(参见第23.5.4.3和23.5.4.4节;第797-798页) )。

特定实现(即特定供应商的标准库实现)可以选择他们想要的任何数据结构。但是,为了符合标准,它们的复杂性必须至少指定