【问题标题】:Associative container with predictable keys: which one to use?具有可预测键的关联容器:使用哪一个?
【发布时间】:2012-10-27 17:16:20
【问题描述】:

一个简单的问题,但答案对我来说并不明显:出于性能原因,从性能角度来看,我应该在以下场景中最好使用哪种地图类型(或者可能是非地图类型?)容器:

  • 键是无符号整数,
  • 插入频繁,
  • 读取访问更加频繁和随机访问,
  • 项以升序键值插入(第一个插入项的键为 0,下一个键为 1,依此类推),
  • 项目被随机删除(因此迟早键列表将有“漏洞”,因为相应的项目已被删除)。移除几乎与插入一样频繁。

我对使用std::map 犹豫不决,因为升序键顺序和频繁删除似乎意味着不断重新平衡搜索树,这对我来说似乎是对性能的浪费。

换句话说:我是否可以从我提前知道项目的键是什么,甚至是键在插入时出现的顺序这一事实中获得性能? (不过我不知道项目的总数。)

【问题讨论】:

  • std::unordered_map 然后,又名哈希表。
  • 如果订单不是一个因素(听起来好像不是),我会考虑使用 unordered_map。如果您的键空间正常并且节点数的顶端也达到稳定,则 unordered_map 具有潜力。
  • 使用std::mapstd::unordered_map 配置文件,看看哪一个效果最好。
  • “正常”键空间是什么意思?
  • 您的键的可能值是多少?如果 [0,N) 范围内的任何值,那么 N 是多少?

标签: c++ stl


【解决方案1】:

如果你确实使用了stl::map——即使只是为了进行分析以与哈希进行比较——你可以利用你的知识“以升序键值插入项目”来大大提高stl::map的效率通过提示插入调用来进行插入操作:

iterator insert ( iterator position_hint, const value_type& x );

...例如,position_hint 将是上一个插入项的迭代器。

【讨论】:

  • 这是一个很棒的itea。我会将它与 unordered_map 进行比较。
【解决方案2】:

如果内存不是问题,为什么不使用一些自定义类型的std::vector?您可以获得最快的访问时间,因为所有元素都是有序的,如果元素被删除,只需保存一个标志。考虑这个代理类:

template<typename RealType>
class MyProxy {
public:
    RealType instance;
    bool isused;


    MyProxy(RealType) { /* TODO */ }
};

然后在您的std::vector 中使用它:

std::vector<MyProxy<MyRealType> > vec;

对于查找,您只需检查索引是否在std::vector 的范围内,并且isused 标志是true。要删除,只需获取索引i 的元素并将标志设置为false。对于插入,您必须 push_back MyProxy&lt;MyType&gt; 的新实例而不是 MyType

这种方法的缺点当然是std::vector不断增长,所以你必须留意内存消耗并最终释放vector,但这可能是查找、插入最快的方法和删除。

【讨论】:

  • 感谢您的建议。不幸的是,一个持久的项目 1 和一个从 2-10000 的洞会造成内存的浪费。不幸的是,我无法重命名这些键。
  • “浪费”取决于映射数据的大小。考虑具有 10,000 个元素的地图可能使用 30,000 个指针来组织数据。那不也是一种“浪费”吗?
猜你喜欢
  • 2011-09-21
  • 2011-09-18
  • 2012-04-07
  • 1970-01-01
  • 2011-12-27
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多