限制std :: set的大小

时间:2011-01-30 13:13:06

标签: c++ lru stdset

我有一个关于std :: set容器的简短问题。现在我正在使用pushback功能来提供我的设置。对于每个push_back,该集合变得越来越大。 我只对最新的30个元素感兴趣......可以删除旧元素。所以我的想法是将集合的大小限制为30个元素左右,并通过这样做摆脱不需要的旧元素。但是,默认情况下,该集不支持限制。我可以偶尔检查一下这个集的大小,然后手动删除多余的元素。 有更聪明的方法吗?

关心Lumpi

4 个答案:

答案 0 :(得分:6)

作为一种解决方案,您可以将set数据结构封装到一个类中,并在该类中控制元素的数量。

答案 1 :(得分:3)

您需要自己构建一个LRU结构。一种方法是使std :: map和std :: list指向彼此的迭代器。那就是:

struct lru_entry {
    std::list<lru_entry *>::iterator lru_iterator;
    std::map<your_data, lru_entry *>::iterator map_iterator;
};

std::list<lru_entry *> lru;
std::map<your_data, lru_entry *> lookup;

每当您在地图中查找条目时,将其关联的列表条目移动到列表的开头。向地图添加条目时,创建一个新的lru_entry,将其添加到map和list中,并更新lru_entry结构中的迭代器。当查找映射超过30个条目时,您可以使用lru列表快速查找最旧的条目。

您可以在this previous stackoverflow question.

中找到有关如何构建LRU列表的更多建议

答案 2 :(得分:1)

该集合不仅不支持限制,它也不会告诉您元素的年龄。创建一个封装容器的新类。然后,该类可以提供在添加元素时或显式地强制执行大小限制的方法。如果根据添加元素的时间进行删除(它针对两端的操作进行了优化),那么队列将是理想的。

答案 3 :(得分:0)

由于我有时间,我会使用集合和列表来完成。该列表只跟踪最后n个插入的元素。还实现了一般擦除。为了获得更好的性能(如果您没有利用已订购集合的事实),您可以考虑使用unordered_set。 (将include <unordered_set>替换为std::set以及将std::unordered_set替换为#include <set> #include <list> #include <assert.h> template<typename T> struct setkeepn { std::set<T> mSet; std::list<T> mLast; void insert(T element) { if (mSet.find(element) == mSet.end()) { assert(mSet.size() == mLast.size()); // put your limit of 30 below if (mSet.size() >= 2) { T extra = mLast.back(); mSet.erase(extra); mLast.pop_back(); } mSet.insert(element); mLast.push_front(element); } } void erase(T element) { typename std::set<T>::iterator lToEraseFromSet = mSet.find(element); if (lToEraseFromSet != mSet.end()) { // linear on the number of elements. typename std::list<T>::iterator lToEraseFromList = std::find(mLast.begin(),mLast.end(), element); assert(lToEraseFromList != mLast.end()); mSet.erase(lToEraseFromSet); mLast.erase(lToEraseFromList); } } }; int main(int argc, const char * argv[]) { setkeepn<int> lTest; lTest.insert(1); lTest.insert(2); lTest.insert(2); lTest.insert(3); printf("should see 2 3\n"); for (auto e : lTest.mSet) { // 2,3 printf("elements: %d\n",e); } lTest.insert(4); lTest.erase(3); printf("should see 4\n"); for (auto e : lTest.mSet) { // 4 printf("elements: %d\n",e); } return 0; }

should see 2 3
elements: 2
elements: 3
should see 4
elements: 4

结果:

{{1}}