【问题标题】:Sparse array in C++C++中的稀疏数组
【发布时间】:2014-01-23 14:16:25
【问题描述】:

我需要一个类似向量的容器,具有整数索引,但省略了一些索引。那么在 C++ 中表示这种稀疏数组的常用方法是什么? 我有一种直觉,std::map 主要用于此类目的。但是对于通常不添加新项目的容器来说,它的速度相当慢。你有什么建议?

UPD:不是很“稀疏”。也许大约 5%。项目主要在初始化步骤期间添加(之后不经常添加)。但是访问很频繁(如果不是很重要,显然我不会开始这个话题)。

【问题讨论】:

  • 尝试使用 boost 或 C++11 的无序映射。
  • “稀疏”有多稀疏?百分比?如果经常期望在两者之间存储附加值,则某些技术可能不合适。您是否需要按索引顺序频繁访问/迭代?
  • 解释它有多慢。
  • boost flat map 是 map 的更快版本,除了插入速度非常慢 (O (n)) 所以你的使用模式必须是 fill map,use map,而不是:fill map,use,add,use , 添加, 删除, 使用...
  • 这似乎是XY Problem。问题显然是性能要求,您假设实现这些要求的方法是使用稀疏数组。

标签: c++ c++11 data-structures map


【解决方案1】:

是的,地图通常是正确的方法。

我建议使用 C++11 unordered_map(基于哈希表)来获得闪电般快速的查找:这几乎是没有连续递增键的最佳选择。

【讨论】:

  • 虽然可能一开始就提出了错误的问题,但我看不出unordered_map 将如何满足对 sparse 容器的假定需求。在被索引之前,不能保证unordered_map 已经分配了任意未分配的索引。
  • @JohnDibling:你为什么需要它?只需将unordered_mapsize_t 设置为所需的映射类型。有什么问题?
  • @John Dibling 但这就是稀疏数组的全部意义:在为数组元素 i 赋值之前,没有为索引 i 分配任何东西。
  • @laune:不,这与稀疏数组相反。稀疏阵列就像一个只有 10% 已满的磁盘。 90% 的空间仍然被分配,从某种意义上说,磁盘实际上并没有增长,但它充满了未初始化的垃圾。
  • @John Dibling wikipedia, "sparse array": "一个简单的数组实现可能会为整个数组分配空间,但是在非默认值很少的情况下,这种实现是低效的。”具有 N 个元素的向量(如数学)始终具有 N 个元素,但稀疏数组的实现不应分配所有无用的存储空间。我不确定您所说的“稀疏容器”是什么意思,但是拥有一个包含大量未使用空间的 container 并不是实现稀疏向量的明智选择。
【解决方案2】:

也许像

std::vector<boost::optional<your_type>> 

对你来说已经足够了。

【讨论】:

  • 可能不是一个好主意。不过,可能是正确的方法。取决于某些事情。
  • 如果对象很大,它应该可以正常工作 - 但如果对象很小并且索引很大,则不会。
  • 这取决于其他一些事情。例如他是否需要快速知道是否填充了特定索引?
【解决方案3】:

项目主要是在初始化步骤中添加的(之后并不经常添加)。但访问频繁

在这种情况下,boost::container::flat_map 对您来说是一个不错的选择。它基本上只是一个排序的向量。优点(从网站上偷来的):

  • 比标准关联容器更快的查找
  • 迭代速度比标准关联容器快得多
  • 小对象的内存消耗更少(如果使用了 shrink_to_fit,对于大对象)
  • 提高缓存性能(数据存储在连续内存中)

一个潜在的缺点:

  • 最坏的线性时间插入和线性时间删除

即使最坏的情况发生在插入或删除过程中(移动底层向量的元素),它仍然没有那么糟糕,这要归功于(1)缓存的良好使用,(2)底层元素的重定位可能是矢量化(矢量指令)。鉴于您的使用模式,您必须在您的应用程序中尝试它以查看插入/删除是否存在问题。

如果flat_map不适合你,我会试试std::unordered_map

【讨论】:

    猜你喜欢
    • 2018-08-22
    • 2022-07-12
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 2011-02-02
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多