简体   繁体   English

C ++ std :: unordered_map复杂度

[英]C++ std::unordered_map complexity

I've read a lot about unordered_map (c++11) time-complexity here at stackoverflow, but I haven't found the answer for my question. 我在stackoverflow上阅读了很多有关unordered_map (c ++ 11) 时间复杂性的信息,但是我没有找到问题的答案。

Let's assume indexing by integer (just for example): 让我们假设使用整数索引(例如):

Insert/at functions work constantly (in average time), so this example would take O(1) Insert / at函数持续工作(平均时间),因此本示例将采用O(1)

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

What I am curious about is how long does it take to iterate through all (unsorted) values stored in map - eg 我很好奇的是,要遍历地图中存储的所有(未排序)值需要多长时间-例如

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

Can I assume that each stored value is accessed only once (or twice or constant-times)? 我可以假定每个存储的值只能访问一次(或两次或固定时间)吗? That would imply that iterate through all values is in N-valued map O(N). 这将意味着遍历所有值都在N值映射O(N)中。 The other possibility is that my example with keys {1,10,100000} could take up to 1000000 iteration (if represented by array) 另一种可能性是,我的键为{1,10,100000}的示例最多可能需要1000000次迭代(如果由数组表示)

Is there any other container, that can be iterated linearly and value accessed by given key constantly? 是否还有其他容器可以线性迭代并可以通过给定键不断访问值?

What I would really need is (pseudocode) 我真正需要的是 (伪代码)

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

Is std::unordered_map the structure I need? std :: unordered_map是我需要的结构吗?

Integer indexing is sufficient, average complexity as well. 整数索引已足够,平均复杂度也是如此。

Regardless of how they're implemented, standard containers provide iterators that meet the iterator requirements. 无论如何实现,标准容器都可以提供满足迭代器要求的迭代器。 Incrementing an iterator is required to be constant time, so iterating through all the elements of any standard container is O(N). 递增迭代器需要保持恒定的时间,因此对任何标准容器的所有元素进行迭代的时间为O(N)。

There's a few different ways that a hash table can be implemented, and I suggest you read more on those if you're interested, but the main two are through chaining and open addressing. 哈希表的实现方式有几种不同的方式,如果您感兴趣,我建议您阅读更多有关哈希表的信息,但主要的两种是通过链接和开放式寻址。

In the first case you have an array of linked lists. 在第一种情况下,您具有一组链接列表。 Each entry in the array could be empty, each item in the hashtable will be in some bucket. 数组中的每个条目都可以为空,哈希表中的每个条目都将位于某个存储桶中。 So iteration is walking down the array, and walking down each non-empty list in it. 因此,迭代是沿着数组行进,并沿着数组中的每个非空列表行进。 Clearly O(N), but could potentially be very memory inefficient depending on how the linked lists themselves are allocated. 显然是O(N),但可能取决于链接列表本身的分配方式,导致内存效率非常低。

In the second case, you just have one very large array which will have lots of empty slots. 在第二种情况下,您只有一个非常大的阵列,其中将有许多空插槽。 Here, iteration is again clearly linear, but could be inefficient if the table is mostly empty (which is should be for lookup purposes) because the elements that are actually present will be in different cache lines. 在这里,迭代显然又是线性的,但是如果表大部分为空(应该用于查找目的),效率可能会很低,因为实际存在的元素将位于不同的缓存行中。

Either way, you're going to have linear iteration and you're going to be touching every element exactly once. 无论哪种方式,您都将进行线性迭代,并且将仅触摸每个元素一次。 Note that this is true of std::map also, iteration will be linear there as well. 注意, std::map也是如此,迭代在那里也是线性的。 But in the case of the maps, iteration will definitely be far less efficient that iterating a vector, so keep that in mind. 但是对于地图而言,迭代肯定比迭代向量效率低得多,因此请记住这一点。 If your use-case involves requiring BOTH fast lookup and fast iteration, if you insert all your elements up front and never erase, it could be much better to actually have both the map and the vector. 如果您的用例需要快速查找和快速迭代,那么如果您将所有元素都插入到前面并且永不擦除,那么实际上同时拥有地图和矢量可能会更好。 Take the extra space for the added performance. 占用额外的空间以增加性能。

The complexity guarantees of all standard containers are specified in the C++ Standard . 所有标准容器的复杂性保证在C ++ Standard中指定。

std::unordered_map element access and element insertion is required to be of complexity O(1) on average and O(N) worst case (cf. Sections 23.5.4.3 and 23.5.4.4; pages 797-798). std::unordered_map元素访问和元素插入的平均复杂度为O(1) ,最坏情况为O(N) (请参见23.5.4.3和23.5.4.4;第797-798页)。

A specific implementation (that is, a specific vendor's implementation of the Standard Library) can choose whatever data structure they want. 特定的实现(即特定供应商对标准库的实现)可以选择他们想要的任何数据结构。 However, to be compliant with the Standard, their complexity must be at least as specified. 但是,为了符合标准,其复杂性必须至少达到规定。

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

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