我正在尝试使用纯STL实现LFU(Least Frequently Used)缓存(我不想使用Boost!)。
要求是:
Key
类似的std::map
对任何元素进行关联访问。UsesCount
属性)。UsesCount
)。问题是:
std::vector
作为项目容器(Key
,Value
,UsesCount
),std::map
作为关联向量的迭代器容器访问和std::make_heap
,std::push_heap
和std::pop_heap
作为向量中的优先级队列实现,映射中的迭代器在堆操作后无效。std::list
(或std::map
)而不是std::vector
,则std::make_heap
等无法编译,因为它们的迭代器不支持aritmetic std::priority_queue
,我无法更新项目优先级。问题是:
感谢您的见解。
答案 0 :(得分:3)
使用*_heap
函数和向量进行make实现似乎非常合适。虽然它会导致更新缓慢。您遇到的迭代器失效问题对于使用向量作为基础数据结构的每个容器都是正常的。这是boost::heap::priority_queue也采用的方法,但由于上述原因,它没有提供可变接口。其他boost::heap data-structures提供更新堆的功能。
似乎有些奇怪:即使您能够使用std::priority_queue
,您仍将面临迭代器失效问题。
直接回答你的问题:你不会错过一些明显的东西。 std::priority_queue
没有它应该有用的那么有用。最好的方法是编写自己的支持更新的堆实现。使其完全兼容STL(特别是分配器识别)是相当棘手的,而不是一个简单的任务。最重要的是,实现LFU缓存。
第一步,查看Boost实现以了解工作量。我不知道第二个参考实现。
要解决迭代器失效问题,您可以随时选择间接到另一个容器,尽管您应该尽量避免它,因为它会产生额外的成本并且会变得非常混乱。
答案 1 :(得分:1)
比保留两个数据结构更简单的方法:
O(n)
)std::nth_element
查找最差的10%(O(n)
)O(n log n)
)因此,向缓存添加新元素的常见情况为O(log n)
,最差情况为O(n log n)
,并且已摊销O(log n)
。
删除最差的10%可能在LFU缓存中有点激烈,因为新条目必须占据前90%或者它们被削减。然后,如果你只删除一个元素,那么新条目仍然需要在下一个新条目之前离开底部,或者它们被删除,并且它们没有时间这样做。所以取决于为什么LFU对你来说是正确的缓存策略,我对它的改变可能是错误的策略,或者它可能仍然没问题。