【问题标题】:Is the STL map container optimized (balanced tree) while constructed?STL 地图容器在构建时是否经过优化(平衡树)?
【发布时间】:2012-05-03 09:13:01
【问题描述】:

如果我将有序(递增)元素序列插入到地图中,最终的二叉树会以某种方式优化吗?或者每个元素都会有一个“正确”的孩子?这会使这样的树非常低效,因为那么查找将是线性的。

我找不到任何有关将过程插入 STL 映射的详细信息。

【问题讨论】:

  • 这完全依赖于实现,除非您不担心可移植性,否则您不应真正依赖实现特定的行为。您应该只依赖@987654321 的行为 @ 应该展示。
  • @Als “依赖于实现特定的行为”与从理解的角度了解行为是如何实现的是有区别的。
  • @Benj:这就是我发表评论的原因,你反对吗?
  • 你们说的都很对。通常人们倾向于依赖这些信息——尽管我只是想知道。 :-)
  • @HWende:如果你想知道,请阅读STL的代码,可以免费下载。如果您说的是 c++ 标准库,而不是 stl,那么您应该阅读您正在使用的特定实现。它可以以不同的方式实现,尽管 rb 树是最常见的,但您肯定会发现不同的实现,例如跳过列表、avl 树、b 树...

标签: c++ stl map


【解决方案1】:

C++11 标准 (23.1) 对关联容器的 insertfind 都要求对数复杂度。从两个迭代器ij 构造它们使得[i, j) 表示一个适当排序的值范围,甚至需要具有线性时间复杂度。这是否意味着“最终的二叉树被优化”,或者地图是否完全是二叉树,都没有说明。

不过,在实践中,std::setstd::map 和它们的多个朋友几乎总是红黑树,因为这是 STL 的原始 HP/SGI 参考实现以及我使用的所有现代 C++ 库所拥有的知道从那个实现派生。

【讨论】:

  • +1 因为它回答了标准规范范围内的问题。
  • @larsmans:在实践中,std::map 被实现为二叉树(红黑或 avl),因为有几个限制:1. 被 const 方法访问时禁止静音,2. 元素必须记忆力稳定。我最近询问了使用跳过列表的问题,但显然它们的表现更差。展开树违反1,B 树(和变体)违反2。事后看来,我认为 2 应该受到挑战,因为 B 树提供了更好的性能(对内存更友好,因此对缓存更友好)。
  • @MatthieuM.:我会得出同样的结论。展开树和跳过列表,但还没有想到 B-树。不过,我怀疑使用 B-tree 或 2-3 树 可以 以牺牲额外的间接级别为代价。
  • @larsmans:但是使用它们的好处是可以获得更好的内存局部性,如果您添加另一个间接级别,您会失去它。这就是为什么我认为稳定性不应该是基本要求的一部分(它与复杂性无关),应该由用户决定他们是否需要额外的间接性。
  • @MatthieuM.:是的。但是,我确实理解稳定性要求,因为该库允许将任意大的结构存储在 std::map 中;在像指针映射这样的专用容器中,可以取消此要求。
【解决方案2】:

一般来说,std::map 是使用红黑树实现的,它是自平衡的。所以是的,它已经过优化。

如果您插入有序数据,自平衡可能会花费更少,因为节点之间的交换不会那么频繁。

【讨论】:

  • 好的,谢谢!您对此信息有任何参考吗? (无意冒犯!)
  • @HWende 未采取任何措施。我没有参考,因为它是定义的实现。这就是为什么我说“一般”。该标准确实保证了一些时间限制,因此插入或删除肯定不会得到 O(n),而是 O(log(n))。
  • 将已排序的数据馈送到自平衡树中总是需要在创建树时浪费大量时间重新平衡,因此第二条语句是不正确的。对于大型数据集,最好尽可能随机读取。
【解决方案3】:

C++ 标准要求 std::map(ISO/IEC 14882 的 23.4.4.3)中任何元素的对数访问时间,因此 std::map 必须实现为自平衡树。

【讨论】:

    【解决方案4】:

    优化了!

    看看SGI's Standard Template Library Programmer's Guide。您会发现以下插入和查找元素的复杂性规范:

    • 插入范围的平均复杂度最多为 O(N * log(size() + N)),
    • 其中 N 是 j - i。查找的平均复杂度最多为对数。

    【讨论】:

    • 在那个特定的 STL 库实现上,它不是标准库。
    • @juanchopanza:但它是 /the/ STL。上次我检查标准时没有定义任何称为 STL 的东西。
    • @PlasmaHH 但 SGI 文档引用了 SGI STL,它没有完全映射到 C++ 标准库。我假设 OP 是指标准库,而不是 STL...
    • @juanchopanza:嗯,我(可能还有其他一些人)假设 OP 意味着 STL。也许是因为 OP 提到了 STL ......人们说 X 时经常指的是 X。除非他们是女孩。但这现在已经离题了。
    • @PlasmaHH 我认为 STL 仍然是一个例外。人们经常说“STL”,他们的意思是“带有容器、算法和模板的 C++ 标准库位”
    【解决方案5】:

    setmap 通常会进行树平衡,因此 find 是 O(log n)。许多操作的复杂性如下所示: http://www.cplusplus.com/reference/stl/

    【讨论】:

      猜你喜欢
      • 2015-04-16
      • 2013-10-21
      • 2013-04-15
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多