如何实现尺寸受限的地图

时间:2018-07-11 06:55:42

标签: c++ memory data-structures hashmap limit

我想实现一个映射,该映射的元素数量不得超过特定限制L。当插入第L+1个元素时,应从地图中删除最旧的条目以清空空间。

我发现了类似的内容:Data Structure for Queue using Map Implementations in Java with Size limit of 5。建议使用链接的哈希图,即也保留所有元素的链接列表的哈希图。不幸的是,那是针对Java的,我需要C ++的解决方案。我在标准库或Boost库中都找不到类似的东西。

这里有同样的故事:Add and remove from MAP with limited size

此处提供了C ++的可能解决方案,但以下未解决我的问题:C++ how to mix a map with a circular buffer?

我将以与此处描述非常相似的方式来实现它。散列图,用于存储键值对和键的链表或双端队列,以保留条目的索引。要插入一个新值,我将其添加到哈希图及其索引的末尾;如果此时has的大小超过限制,我将弹出索引的第一个元素,并从has中删除带有该键的条目。与添加到哈希映射表一样简单,复杂。

删除条目需要在索引上进行迭代才能从此处删除键,这对于链接列表和双端队列都具有线性复杂性。 (双端队列还具有删除元素本身具有线性复杂性的缺点。)因此,看来对此类数据结构的删除操作不会保留复杂性,因为底层具有映射。< / p>

问题是:是否需要增加复杂性,还是有一些聪明的方法来实现有限的地图数据结构,以便插入和删除都保持相同的复杂性?


糟糕,刚发布并立即意识到一些重要的事情。索引的大小也受到限制。如果该限制是恒定的,则也可以将其迭代的复杂性视为恒定的。

好吧,此限制为移除操作的费用提供了上限。

如果限制非常高,您可能仍希望使用不涉及线性迭代而不是索引的解决方案。

2 个答案:

答案 0 :(得分:1)

我仍将使用关联容器进行直接访问,并使用顺序访问容器以便轻松删除较旧的项目。让我们看一下所需的访问方法:

  • 在给定其键=>的情况下访问元素,关联容器允许直接访问
  • 添加新的键值对
    • 如果地图不完整,则很容易:在序列容器上push_back,并简单地添加到关联容器中
    • 如果映射已满,则必须执行上述操作,但是必须删除最旧的元素=>序列容器上的front将提供该元素,而pop_fronterase将删除它,只要密钥包含在序列容器中
  • 删除其键=>给出的元素非常简单,以从关联容器中删除,但是只有list允许在恒定的时间内删除元素,前提是您具有迭代器。好消息是,在列表中删除或插入元素不会使指向其他元素的迭代器无效。

由于您对保持键的排序没有任何要求,因此我将unordered_map用于关联容器,并将list用于序列1。附加要求是list必须包含密钥,并且unordered_map必须包含对list中其对应元素的迭代器。该值可以在两个容器中。因为我假设主要访问权限将是直接访问权限,所以我会将值存储在地图中。

它归结为:

  • 一个list<K>以允许识别最早的密钥
  • 一个unordered_map<K, pair<V, list<K>::iterator>>

它将密钥的存储空间增加一倍,并添加一个附加的迭代器。但是键应该不会太大,list::iterator通常只包含一个指针:这会为速度改变少量内存。

这足以提供恒定的时间

  • 密钥访问
  • 插入新项目
  • 项的密钥删除

答案 1 :(得分:0)

您可能想看看Boost.MultiIndex MRU example