【问题标题】:What's the time complexity of iterating through a std::set/std::map?迭代 std::set/std::map 的时间复杂度是多少?
【发布时间】:2012-07-31 13:34:49
【问题描述】:

遍历std::set/std::multiset/std::map/std::multimap 的时间复杂度是多少?我相信它在集合/地图的大小上是线性的,但不太确定。语言标准中有规定吗?

【问题讨论】:

  • 整个容器的迭代总是O(n)至少(我想真的很愚蠢的实现可能会使它更糟

标签: c++ stl time-complexity big-o std


【解决方案1】:

draft C++11 standard N3337 中可以在第 24.2.1 节第 8 段中找到答案:

所有类别的迭代器只需要那些函数 可在恒定时间内实现给定类别(摊销)。

由于对迭代器的每个操作都必须是常数时间,因此遍历n 元素必须是O(n)

【讨论】:

  • 如果 map/set 实现为带有父指针的二叉树,则遍历所有元素将最多访问每个树节点 3 次。如果实现是一个有父指针的b-tree,每个节点最多会被访问2*n + 1次,n是节点中的元素个数。在这两种情况下,这意味着每个迭代步骤的平均时间复杂度恒定。我不知道有任何其他合规的方式来实现地图/设置。
  • 其实,对于std::setstd::multisetstd::mapstd::multimap,如果实现为红黑树(这是最常见的情况),最坏情况复杂度为查找下一个/上一个有序元素是O(log N)。当然,在实践中,平均情况是摊销常数。
【解决方案2】:

我相信它在集合/地图的大小上是线性的,但不是这样 当然。

没错。遍历整个集合或地图是O(N)

【讨论】:

  • 为什么要强调摊销?对于所有已知的实现,它是 O(N)。证明很简单。容器setmap 使用红黑树实现。每次从一个节点移动到另一个节点时,只需在两个节点之间画一条线。完成迭代后,您会看到所有行都翻了一番,并且您访问了每个节点恰好两次。
  • @Elliott 没错。在二叉树中查找下一个最高元素需要 O(log N) 时间。
  • @IgorMikushkin。由于您的两个 cmets,并且进一步考虑,我可以看到它大致是 2n 时间,所以 O(n)。我也意识到我对你如何找到元素的描述是错误的。你帮助了我——我一直以为是O(n*log(n))。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-22
  • 2020-10-13
  • 2015-10-04
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多