struct Node { //双向链表的节点
int key; //键
int val; //值
int freq; //频率
Node* prev; //前一个节点
Node* next; //后一个节点
//无参构造函数
Node () : key(-1), val(-1), freq(0), prev(nullptr), next(nullptr) {}
//带参构造函数
Node (int _k, int _v) : key(_k), val(_v), freq(1), prev(nullptr), next(nullptr) {}
};
struct FreqList { //双向链表
int freq; //频率
Node* vhead; //链表头
Node* vtail; //链表尾
//构造函数
FreqList (int _f) : freq(_f), vhead(new Node()), vtail(new Node()) {
vhead->next = vtail;
vtail->prev = vhead;
}
};
class LFUCache {
private:
unordered_map<int, Node*> occ; //键 和 键值对 对应
unordered_map<int, FreqList*> freq_map; //频率 和 双向链表对应
int sz; //大小
int min_freq; //最小的频率
public:
//构造函数
LFUCache (int capacity) : sz(capacity) {}
//判断双向链表是否为空
bool empty(FreqList* l) {
return l->vhead->next == l->vtail ? true : false;
}
//删除双向链表中的节点
void deleteNode (Node* t) {
t->prev->next = t->next;
t->next->prev = t->prev;
}
//将节点添加到头部
void addHead (Node* t) {
int freq = t->freq; //获得节点的频率
if (freq_map.find(freq) == freq_map.end()) { //在频率哈希表中找不到该频率
freq_map[freq] = new FreqList(freq); //新建一个双向链表
}
FreqList* l = freq_map[freq]; //获得该双向链表
t->next = l->vhead->next; //将节点添加到链表头
l->vhead->next->prev = t;
t->prev = l->vhead;
l->vhead->next = t;
}
//删除双向链表的尾部
void popTail () {
Node* t = freq_map[min_freq]->vtail->prev; //获得最后一个节点
deleteNode(t); //删除该节点
occ.erase(t->key); //删除occ中的映射
}
int get (int key) {
int res = -1;
if (occ.find(key) != occ.end()) { //找到了key
Node* t = occ[key]; //获得该key对应的节点
res = t->val; //保存结果
deleteNode(t); //删除这个节点
t->freq++; //更新访问频率
if (empty(freq_map[min_freq])) min_freq++; //如果最小频率对应的链表为空,将最小频率加1
addHead(t); //将t添加到对应频率的双向链表的最前面
}
return res; //返回结果
}
void put (int key, int value) {
if (sz == 0) return; //如果缓存的大小为0,返回
if (get(key) != -1) { //如果找的到
occ[key]->val = value; //更新值
}
else {
if (occ.size() == sz) { //如果已经满了
popTail(); //删除最后一个节点
}
Node* t = new Node(key, value); //生成一个新的节点
occ[key] = t; //添加到映射表occ中
min_freq = 1;//新插入的 频率一定最少, 为1 //设置最小的频率为1
addHead(t); //添加到对应频率的最前面
}
}
};
/**
* 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);
*/
LeetCode460 LFU缓存
猜你喜欢
转载自blog.csdn.net/m0_38062470/article/details/114452149
今日推荐
周排行