LFU c++11 实现,当插入数值数量超过最大容量时,同样频率删除最久未使用的key
template <typename key_t, typename value_t>
class LFUCache {
private:
struct CacheNode {
key_t key;
value_t value;
int frequency;
};
std::size_t _capacity;
std::unordered_map<key_t, typename std::list<CacheNode>::iterator> _cache; // key:frequency
std::unordered_map<int, std::list<CacheNode>> _frequency; // frequency:cacheNode
int _minFrequency; // 当前最小的访问频率
public:
LFUCache(std::size_t capacity) {
_capacity = capacity;
_minFrequency = 0;
}
key_t get(key_t key) {
auto iter = _cache.find(key);
if (iter == _cache.end()) {
throw std::logic_error("can not found the key!");
}
auto &cacheNodeIter = iter->second;
// update _frequency
auto oldFrequency = cacheNodeIter->frequency;
cacheNodeIter->frequency += 1;
_frequency[oldFrequency + 1].splice(_frequency[oldFrequency + 1].end(), _frequency[oldFrequency], cacheNodeIter);
if( _frequency[oldFrequency].empty()){
_frequency.erase(oldFrequency);
}
// update _minFrequency
if (_frequency[_minFrequency].empty() && _minFrequency == oldFrequency) {
_minFrequency = oldFrequency + 1;
}
return cacheNodeIter->value;
}
void put(key_t key, value_t value) {
if (_capacity <= 0) {
throw std::logic_error("capacity is zero!");
}
auto iter = _cache.find(key);
if (iter == _cache.end()) { // 不存在
if (_cache.size() >= _capacity) {
auto &node = _frequency[_minFrequency].front();
_cache.erase(node.key);
_frequency[_minFrequency].pop_front();
}
_frequency[1].push_back({key, value, 1});
_cache.emplace(key, std::prev(_frequency[1].end()));
_minFrequency = 1;
} else { // 存在
get(key); // 更新计数
iter->second->value = value; // 更新值
}
}
};