手把手带你手撕LFU
文章目录
LFU的淘汰策略是优先淘汰最久的使用频率最低的那个
所以
第一步
put
- 如果没有超过容量,需要知道key对应的插入那么一个频率块,需要知道当前的频率块在里面删除
- 如果超过了,要知道最小的频率在哪里
get
- 快速知道key对应的value在哪里
- 需要快速的删除,插入
所以我们设计如下
struct Node: 包括key value freq 三个属性
unordered_map<int,List<Node>> // key是频率 value是对应存放频率的地方
unordered_map<int,List<NOde>::iter> // key 是键值 value 指向key存放的位置
代码
#include <bits/stdc++.h>
using namespace std;
struct Node {
int key;
int value;
int freq;
Node(int a, int b, int c) : key(a), value(b), freq(c) {}
};
class LFUCache {
public:
LFUCache(int capacity) : size_(capacity) {}
int get(int key) {
int res = -1;
if (key2iter_.find(key) != key2iter_.end()) { // 如果找到了
auto iter = key2iter_[key];
Node node = *iter;
res = node.value;
delete_key(iter->key);
node.freq++;
addkey(node.key, node.value, node.freq);
}
return res;
}
void delete_key(int key) { // 删除某个键为key node
auto iter = key2iter_[key];
int delete_freq = iter->freq;
preq2data_[delete_freq].erase(iter);
key2iter_.erase(key);
if (preq2data_[delete_freq].empty()) { // 删除完以后空了
preq2data_.erase(delete_freq); // 链表相应去除
if (delete_freq == Min_freq) {
Min_freq++;
}
}
}
void addkey(int key, int value, int freq) { // 在某个频率块加一个node
// 新增的fre是1
preq2data_[freq].push_back(Node(key, value, freq));
key2iter_[key] = --preq2data_[freq].end();
if (freq == 1) {
Min_freq = 1;
}
}
void put(int key, int value) {
if (size_ == 0) {
return;
}
if (key2iter_.find(key) == key2iter_.end()) { // 原来没有这个节点
if (key2iter_.size() == size_) { // 容量达到最大
// 先进行淘汰
delete_key(preq2data_[Min_freq].front().key);
addkey(key, value, 1);
} else {
addkey(key, value, 1);
}
} else { // 存在
Node node = *key2iter_[key];
delete_key(key);
node.freq++;
node.value = value;
addkey(key, value, node.freq);
}
// show();
}
private:
unordered_map<int, list<Node>> preq2data_;
unordered_map<int, list<Node>::iterator> key2iter_;
int size_;
int Min_freq = 0;
};
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache* obj = new LFUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
这里的关键点就是
pre2data的键是频率一定不可以弄错- 如果这个
pre2data某一个值被我们删除完了,那么需要把对用的频率进行删除,如果删除的频率等于最小的频率那么最小频率直接加1 - 为什么最小频率直接加1,因为删除之后出现在
get以及put之后,put会把min_freq置1,而加一是因为,get后频率会加一

本文详细介绍了LFU(Least Frequently Used)缓存淘汰策略的原理,并提供了一段C++实现代码。LFU策略优先淘汰最久未使用且使用频率最低的元素。文章通过`put`和`get`操作解释了如何维护频率块和键值映射,并讨论了频率块清空及最小频率更新的处理。核心数据结构包括`unordered_map`来存储频率块和键值迭代器,确保高效查找和更新。
1629

被折叠的 条评论
为什么被折叠?



