struct LFUNode
{
int freq;
list<pair<int, int>> vals;
LFUNode(int f = 0) : freq(f) { }
};
typedef list<LFUNode>::iterator iptr;
typedef list<pair<int, int>>::iterator jptr;
class LFUCache {
public:
LFUCache(int capacity) : capacity_(capacity) { }
int get(int key) {
auto it = kv_.find(key);
if (it == kv_.end())
return -1;
kv_[key] = promote(key);
return kv_[key].second->second;
}
void put(int key, int value) {
if (capacity_ <= 0)
return;
if (kv_.find(key) == kv_.end()) {
// insert new element
if (kv_.size() >= capacity_)
evict();
iptr i = cache_.begin();
if (i == cache_.end() || i->freq != 1)
i = cache_.insert(i, LFUNode(1));
jptr j = i->vals.insert(i->vals.end(), { key,value });
kv_[key] = { i, j };
}
else {
kv_[key] = promote(key, value);
}
}
private:
pair<iptr, jptr> promote(int key, int val = -1) {
iptr i;
jptr j;
// unpack kv_[key]
tie(i, j) = kv_[key];
// k refers to the next element in bucket
iptr k = next(i);
// val == -1 means that get() invoked promote
// so we don't need to change it's value
if (val == -1)
val = j->second;
// retrive the frequence
int freq = i->freq + 1;
// erase the key-value pair in the list
i->vals.erase(j);
if (i->vals.empty())
cache_.erase(i);
// check to see if we need to create a new element
if (k == cache_.end() || k->freq != freq)
i = cache_.insert(k, LFUNode(freq));
// if the slot already exists
else
i = k; // i points to k
// append key-value pair in the list
j = i->vals.insert(i->vals.end(), { key, val });
// i->vals.emplace_back(key, j->second);
// j = i->vals.end() - 1;
return{ i,j };
}
void evict() {
// i points to the first element of the frequency list
// so i refers to the smallest frequency
iptr i = cache_.begin();
// j refers to the least recently used ket-value pair
jptr j = i->vals.begin();
// erase this pair in the map
kv_.erase(j->first);
// erase j
i->vals.erase(j);
// if there is no more pair in the i list
// delete i
if (i->vals.empty())
cache_.erase(i);
}
private:
int capacity_;
list<LFUNode> cache_;
unordered_map<int, pair<iptr, jptr> > kv_;
};
【常数时间】LFU(Least Frequently Used)基于频次的缓存淘汰算法C++实现
最新推荐文章于 2022-07-16 23:29:20 发布