【问题标题】:std::multiset<int> vs. std::map<int, std::size_t> for keeping multiple repeatable integer valuesstd::multiset<int> vs. std::map<int, std::size_t> 用于保持多个可重复的整数值
【发布时间】:2012-05-30 09:40:57
【问题描述】:

我想创建一个记录来保存关于

的信息
  • a) 存在什么样的元素和
  • b) 存在的每种元素的数量

在树的一个节点中。我将只为叶节点显式存储此信息,而父节点的信息可以通过组合所有子节点的信息来获得(例如,孩子 1 有 3 个 A 对象,1 个 B 对象,孩子 2 有 1 A 的对象,C 的 2 个对象 -- parent 有 A 的 4 个对象,B 的 1 个对象和 C 的 2 个对象。

在向父节点请求此信息时,我会小心,不要先请求、使用和丢弃子节点的信息,然后再请求其父节点,但向上构造将是常见的手术。其他两个常见的操作直接来自我存储的内容:X 种类的对象是否存在?X 种类的对象有多少?以及如何存在多种对象?

对象种类以整数表示,对象编号始终为整数值。什么是更好的选择(以及所选选择的论据):

  • 使用std::multiset&lt;int&gt;,并使用std::multiset::count()std::multiset::find() 操作(更容易合并但元素重复,难以获得不同元素的总数)
  • 使用std::map&lt;int, std::size_t&gt;,类型作为键,对象数量作为值(没有重复的元素,std::map::find() 函数存在,大小给出了存储的对象类型的正确数量,但访问不存在的元素会增加尺寸无意)

感谢您的建议!

【问题讨论】:

  • @larsmns 我无法在工作环境中测试它们(我正在实施一件大事,这个组件将用于尚未实施的事情,也许还没有计划中的事情) .而且,我无法预测操作的确切比例,因此我无法模拟工作环境。谢谢你的size_t
  • @larsmans 虽然我不是“总是不加推理地配置文件”的大朋友——参数,+1 用于传播无符号类型。有符号类型比无符号类型更有意义的情况通常要少得多。
  • @ChristianRau:你说的很对,很抱歉。我仔细考虑了这个问题并发布了答案; mapmultiset 实际上可以具有不同的空间复杂度,具体取决于键的分布。

标签: c++ stl containers


【解决方案1】:

要根据比较谓词存储总共 n 个具有 k 个不同值的项目,std::multiset 分配 n 个二叉搜索树节点(*)。 std::map 仅分配 k(稍大)节点。

当您的比较谓词可以认为两个项目相等但仍必须显式存储时,您将使用std::multiset,因为它们在比较谓词不检查的某些方面有所不同。此外,迭代 multiset 会生成 n 个项目中的每一个,而 map 将生成每个 k 个不同的项目以及每个项目的计数。

如果项目只是整数,请使用std::map。然后,您的“有多少不同的项目”查询将只是对 size 的调用,它会在恒定时间内运行。

仅当您使用operator[] 访问节点时,您声称“访问不存在的元素会无意中增加大小”才是正确的。 find 没有表现出这种行为。

(*) C++ 标准不保证这些容器被实现为(平衡的)BST,但在我见过的所有实现中,它们都是。

【讨论】:

    【解决方案2】:

    排序后的std::vector&lt;int&gt; 怎么样?您需要的操作可以满足如下:

    • X 种类的对象存在吗? std::binary_search
    • 有多少种 X 的对象? std::equal_range,从 .second 中减去 .first
    • 目前有多少种对象?
      • std::unique_copy 后跟 size() 的副本,或者...
      • 使用单独的计数器,在插入向量之前调用std::binary_search

    与树状结构相比,这种方法的优点是缓存局部性(所有数据都是连续的)和更低的内存占用。在不了解您的数据的情况下,我无法确定它会更快还是更慢。您必须对其进行剖析才能找到答案,但我预感它的性能会比您预期的要好。

    这里最大的权衡是表现力。 std::map 方法可能在逻辑上传达您正在做的事情方面做得更好,即对象 ID 和计数之间的关系。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      • 2016-08-28
      • 1970-01-01
      相关资源
      最近更新 更多