【问题标题】:what is the complexity of iterating an unordered_map迭代 unordered_map 的复杂性是什么
【发布时间】:2021-06-30 18:47:21
【问题描述】:

迭代使用散列和链接实现的 unordered_map 的复杂性是多少?具体来说,这是否涉及遍历所有存储桶,在这种情况下,复杂性是 O(Buckets + NElements) 与理想的,例如O(NElements)

【问题讨论】:

  • 来自iterator.requirements.general,“迭代器的所有类别只需要在恒定时间内(摊销)对给定类别可实现的那些功能。因此,迭代器的需求表和概念定义没有指定复杂。”所以增量是 O(1),穿过整个容器是 O(N)。
  • @1201ProgramAlarm:该要求似乎与迭代器适配器(以及范围提案中的过滤器等)不兼容。

标签: c++ c++11 unordered-map


【解决方案1】:

遍历unordered_map 的复杂度是多少?

O(N) 其中 N 是存储的元素数。标准的most relevant part

迭代器的所有类别只需要在恒定时间内(摊销)对给定类别可实现的那些函数。因此,迭代器的需求表没有复杂度列。

您可以在例如this answer

..使用散列和链式实现?

所有无序映射都使用链式散列 - 请参阅 here

具体而言,这是否涉及遍历所有存储桶,在这种情况下,复杂度是 O(Buckets + NElements) 与理想的,例如O(N个元素)

它完成了您所说的“理想”。在 GCC 的情况下,桶将迭代器保存到一个单链表中,并且在迭代容器时通常会遍历更短的列表。通常是因为即使不更改默认的max_load_factor() 1.0,桶的数量也有可能完全等于元素的数量——任何比这更多的元素都会触发调整大小。但是,当几乎所有元素都被删除时,迭代的大 O 效率变得更加重要,因为桶的数量不会自动向下调整(即减少)。

【讨论】:

  • 感谢 Tony,有了单链表,大概那里的节点有一个链接返回到它们所属的存储桶以处理删除?
  • @user3882729:好问题。实际上,GCC的无序容器迭代器只有一个指向节点的指针,而节点只有一个指向next-node和storage的指针,但是在“storage”中既有值对象又有哈希码,所以可以划分通过桶计数预先计算的哈希值来找到桶。您可以在 gdb 中轻松看到:(gdb) print *it._M_cur $2 = {[...]{<std::__detail::_Hash_node_base> = {_M_nxt = 0x41a330}, _M_storage = [...] {__data = "\006\000\000", __align = {<No data fields>}}}}, _M_hash_code = 6}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-06
  • 1970-01-01
  • 2012-09-17
  • 2019-04-30
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
相关资源
最近更新 更多