繁体   English   中英

C ++ std :: unordered_map复杂度

[英]C++ std::unordered_map complexity

我在stackoverflow上阅读了很多有关unordered_map (c ++ 11) 时间复杂性的信息,但是我没有找到问题的答案。

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

Insert / at函数持续工作(平均时间),因此本示例将采用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是我需要的结构吗?

整数索引已足够,平均复杂度也是如此。

无论如何实现,标准容器都可以提供满足迭代器要求的迭代器。 递增迭代器需要保持恒定的时间,因此对任何标准容器的所有元素进行迭代的时间为O(N)。

哈希表的实现方式有几种不同的方式,如果您感兴趣,我建议您阅读更多有关哈希表的信息,但主要的两种是通过链接和开放式寻址。

在第一种情况下,您具有一组链接列表。 数组中的每个条目都可以为空,哈希表中的每个条目都将位于某个存储桶中。 因此,迭代是沿着数组行进,并沿着数组中的每个非空列表行进。 显然是O(N),但可能取决于链接列表本身的分配方式,导致内存效率非常低。

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

无论哪种方式,您都将进行线性迭代,并且将仅触摸每个元素一次。 注意, std::map也是如此,迭代在那里也是线性的。 但是对于地图而言,迭代肯定比迭代向量效率低得多,因此请记住这一点。 如果您的用例需要快速查找和快速迭代,那么如果您将所有元素都插入到前面并且永不擦除,那么实际上同时拥有地图和矢量可能会更好。 占用额外的空间以增加性能。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM