LRU算法:是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法。该算法的思路是,发生缺页中断时,选择未使用时间最长的页面置换出去。 [1] 从程序运行的原理来看,最近最少使用算法是比较接近理想的一种页面置换算法,这种算法既充分利用了内存中页面调用的历史信息,又正确反映了程序的局部问题。
要实现LRU,就要使用其他数据结构实现上述几个函数:
第一种方法:
哈希表+双端队列
class LRUCache {
private:
int num;//元素数量
int _capacity;//缓存空间
unordered_map<int, int> res;
deque<int> rem;
public:
LRUCache(int capacity) {
_capacity = capacity;
num = 0;
}
void adjust(int key) {//调整位置,也可以认为调整优先级,那些长时间未访问或者使用的数据优先级要靠后,最近使用的优先级就考前
rem.erase(find(rem.begin(), rem.end(), key));
rem.push_front(key);
}
int get(int key) {
if (res.count(key) == 0)
return -1;
else {
adjust(key);
return res[key];
}
}
void put(int key, int value) {
if (get(key) == -1) {
if (num + 1 > _capacity) {
res.erase(rem.back());
rem.pop_back();
}
res[key] = value;
rem.push_front(key);
num++;
}
else {//注意这里我们调用了get(key)就已经调整了位置
res[key] = value;
}
}
};
第二种方法:
class LRUCache1 {
private:
int _capacity;
list<pair<int, int>> res;//双向链表
unordered_map<int, list<pair<int, int>>::iterator> map;
public:
LRUCache1(int capacity) : _capacity(capacity) {}
int get(int key) {
if (map.count(key) == 0)return -1;
res.splice(res.begin(), res, map[key]);//调整位置
return map[key]->second;
}
void put(int key, int value) {
if (get(key) == -1) {
if (res.size() == _capacity) {
map.erase(res.back().first);//删除长时间没使用的元素
res.pop_back();
}
res.push_front({ key,value });//新进的元素要放在头部
map[key] = res.begin();//指针初始化
}
else {
map[key]->second = value;
}
}
};