LFU
LFU(least frequently used (LFU) page-replacement algorithm)。即最不经常使用页置换算法,要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。
unordered_map<int, list<node>::iterator> map_key;
unordered_map<int, list<node>> map_cnt;
int min_cnt = 0;
int LFUGet(int key)
{
auto findIter = map_key.find(key);
if (findIter == map_key.end())
{
return -1;
}
else
{
int cnt = findIter->second->cnt;
int val = findIter->second->v;
map_cnt[cnt].erase(findIter->second); //移除当前链表的尾部
map_cnt[cnt+1].push_front(node(key, val, cnt + 1)); //添加到新链表的头部
map_key[key] = map_cnt[cnt+1].begin();
//修改最小调用次数 min_cnt
if (min_cnt == cnt && map_cnt[cnt].size() == 0)
{
min_cnt++;
}
return val;
}
}
void LFUSet(int key, int val, int k)
{
auto findIter = map_key.find(key);
//当前数据不存在,需要新插入
if (findIter == map_key.end())
{
//缓存没有剩余的空间
if (map_key.size() >= k)
{
int deleteKey = map_cnt[min_cnt].back().k;
map_cnt[min_cnt].pop_back();
map_key.erase(deleteKey);
}
map_cnt[1].push_front(node(key, val, 1));
map_key[key] = map_cnt[1].begin();
min_cnt = 1;
}
//当前数据已经存在
else
{
int cnt = findIter->second->cnt;
map_cnt[cnt].erase(findIter->second);
map_cnt[cnt + 1].push_front(node(key, val, cnt + 1));
map_key[key] = map_cnt[cnt + 1].begin();
//删除了数据之后需要调整最小调用次数,如果被删除的列表为空,则调整为当前key的次数
if (min_cnt == cnt && map_cnt[cnt].size() == 0)
{
min_cnt++;
}
}
}
vector<int> LFU(vector<vector<int> >& operators, int k) {
vector<int> res;
for (auto& it : operators)
{
if (it[0] == 1)
{
LFUSet(it[1], it[2], k);
}
else
{
res.push_back(LFUGet(it[1]));
}
}
return res;
}