#include<iostream>
#include<unordered_map>
using namespace std;
//初始化缓存节点信息
struct Node {
int key, val, freq;
Node(int _key, int _val, int _freq) :key(_key), val(_val), freq(_freq) {}
};
class LFUCache
{
private:
int minfreq; //当前缓存中使用的最少的频率值
int capacity; //容量
//以键值 key 为索引,每个索引存放对应缓存在 FreqTable中链表里的地址,
unordered_map<int, list<Node>::iterator> KeyTable;
//以频率 freq 为索引,每个索引存放一个双向链表 双向链表的数据域中 存放node结构体
unordered_map<int, list<Node>> FreqTable;
public:
LFUCache(int _capcity) {
minfreq = 0;
capacity = _capcity;
KeyTable.clear();
FreqTable.clear();
}
int get(int key) {
if (capacity == 0)
return -1;
auto keyIter = KeyTable.find(key);
if (keyIter == KeyTable.end())
return -1;//找不到这个key值就返回-1
list<Node>::iterator nodeIter = keyIter->second;
int val = nodeIter->val, freq = nodeIter->freq;
//删除FreqTable 中索引为freq的 nodeIter节点
FreqTable[freq].erase(nodeIter);
// 如果当前链表为空,我们需要在哈希表中删除,且更新minFreq
if (FreqTable[freq].size() == 0) {
FreqTable.erase(freq);
if (minfreq == freq)
minfreq++;
}
//插入到freq + 1中的前面
FreqTable[freq + 1].push_front(Node(key, val, freq + 1));
KeyTable[key] = FreqTable[freq + 1].begin();
return val;
}
void put(int key, int val) {
if (capacity == 0) return;
auto keyIter = KeyTable.find(key);
if (keyIter == KeyTable.end()) { //找不到这个key值
//缓存满了 删除缓存
if (KeyTable.size() == capacity) {
// 通过 minFreq 拿到 freq_table[minFreq] 链表的末尾节点
Node MinFreqBackNode = FreqTable[minfreq].back();
//根据MinFreqBackNode的key值 删除 KeyTable中的键值对
KeyTable.erase(MinFreqBackNode.key);
FreqTable[minfreq].pop_back();
// 如果当前链表为空,我们需要在哈希表中删除,且更新minFreq
if (FreqTable[minfreq].size() == 0) {
FreqTable.erase(minfreq);
}
}
FreqTable[1].push_front(Node(key, val, 1));
KeyTable[key] = FreqTable[1].begin();
minfreq = 1;
}
else { //如果找到这个key
list<Node>::iterator nodeIter = keyIter->second;
int freq = nodeIter->freq;
FreqTable[freq].erase(nodeIter);
if (FreqTable[freq].size()==0)
{
FreqTable.erase(freq);
if (minfreq == freq)
minfreq++;
}
FreqTable[freq + 1].push_front(Node(key, val, freq + 1));
KeyTable[key] = FreqTable[freq + 1].begin();
}
}
};
int main() {
LFUCache cache = LFUCache(2);
cout << "插入 key = 1,val=10" << endl;
cache.put(1, 10);
cout << "插入 key = 2,val=20" << endl;
cache.put(2, 20);
cout <<"查询key为1 对应的 val: " << cache.get(1) << endl;
cout << "没有插入key为3的时候 查询key为3 对应的 val:" << cache.get(3) << endl;
cout << "插入 key = 3,val=30" << endl;
cache.put(3, 30);
cout << "查询key为2 对应的 val" << endl;
if (cache.get(2) == -1)
{
cout << "key=2 已经被淘汰" << endl;
}
else {
cout << "key=2 仍然存在" << endl;
}
system("pause");
return 0;
}
参考
https://leetcode-cn.com/problems/lfu-cache/solution/lfuhuan-cun-by-leetcode-solution/官方题解