【发布时间】:2012-07-10 08:41:01
【问题描述】:
我正在尝试使用纯 STL 实现 LFU(最不常用)缓存(我不想使用 Boost!)。
要求是:
- 使用
Key对任何元素进行关联访问,例如std::map。 - 能够释放最低优先级项目(使用其
UsesCount属性)。 - 能够更新任何项目的优先级 (
UsesCount)。
问题是:
- 如果我使用
std::vector作为项目容器(Key、Value、UsesCount)、std::map作为用于关联访问的向量的迭代器容器和std::make_heap、std::push_heap和std::pop_heap作为vector内的优先队列实现,map中的迭代器在堆操作后无效。 - 如果我在之前的配置中使用
std::list(或std::map)而不是std::vector,则无法编译std::make_heap等,因为它们的迭代器不支持算术运算。 - 如果我想使用
std::priority_queue,我无法更新项目优先级。
问题是:
- 我是否遗漏了一些显而易见的问题如何解决?
- 您能否以一些纯 C++/STL 实现的 LFU 缓存满足之前的要求为例?
感谢您的见解。
【问题讨论】:
-
“堆操作后映射中的迭代器无效” - 通过相反的方式解决此问题 - 将数据放在
map中,它甚至不会被移动如果其他元素被插入/删除。然后将映射迭代器放入您的向量中并从中构建一个堆。但是,您可能仍然缺少有效更新项目优先级的能力,因此这不是答案。 -
感谢您提出另一个我没有想到的想法。但是,如果我有
std::vector的std::map迭代器,我该如何定义它们的比较运算符,这将在UsesCount属性的指针对象内部查看,以便能够在插入项目后使用std::make_heap修复堆或UsesCount更新? -
使用比较函子,例如:
bool operator()(MapIter a, MapIterB) { return a->second.UseCount < b->second.UseCount; } -
只是在迂腐方面,你确定你不是指最经常使用(MFU)/最少最近使用(LRU) ?最不常用的,为什么要缓存这些?
-
引用维基百科“LFU 计算需要的项目的频率。最不经常使用的项目首先被丢弃。”,这意味着它就是我想要的。