什么是LRU Cache
LRU
是
Least Recently Used
的缩写,意思是
最近最久使用
,它是一种
Cache
替换算法。
什么是Cache?
狭义 的Cache
指的是位于
CPU
和主存间的快速
RAM
, 通常它不像系统主存那样使用
DRAM
技术,而使用昂贵但较 快速的SRAM
技术。 广义上的
Cache
指的是位于速度相差较大的两种硬件之间, 用于协调两者数据传输速度差异的结构。除了CPU
与主存之间有
Cache
, 内存与硬盘之间也有
Cache
,乃至在硬盘与网络之间也有某种意义上的Cache
──
称为
Internet
临时文件夹或网络内容缓存等。
Cache
的容量有限,因此当
Cache
的容量用完后,而又有新的内容需要添加进来时, 就需要挑选并舍弃原有
的部分内容,从而腾出空间来放新内容。
LRU Cache的实现
实现
LRU Cache
的方法和思路很多,但是要保持高效实现
O(1)
的
put
和
get
,那么使用双向链表和哈希表的搭配是最高效和经典的。使用双向链表是因为双向链表可以实现任意位置O(1)
的插入和删除,使用哈希表是因为哈希表的增删查改也是O(1)
unordered_map
的
value type
放成
list<pair<int, int>>::iterator,因为这样,当
get
一个已有的值以后,就可以直接找到
key
在
list
中对应的
iterator
, 然后将这个值移动到链表的头部,保持LRU
#include <list>
#include <unordered_map>
#include <iostream>
using namespace std;
class LRUCache
{
public:
LRUCache(int capacity) : _capacity(capacity) {}
int get(int key)
{
int val = -1;
//在map中找key
auto it = _ump.find(key);
//找到了
if (it != _ump.end())
{
val = it->second->second;
//将该节点调整到链表头部
_list.erase(it->second);
_list.push_front(make_pair(key, val));
//_list.splice(_list.begin(),_list,it->second);
//更新哈希表中val的迭代器
_ump[key] = _list.begin();
}
return val;
}
// void put(int key, int value)
// {
// auto it = _ump.find(key);
// if (it != _ump.end())
// {
// _list.erase(it->second);
// }
// _list.push_front(pair<int,int>(key,value));
// _ump[key] = _list.begin();
// if(_ump.size()>_capacity)
// {
// _ump.erase(_list.back().first);
// _list.pop_back();
// }
// }
void put(int key, int value)
{
auto it = _ump.find(key);
if(it!=_ump.end())
{
//找到了
_list.erase(it->second);
_list.push_front(make_pair(key,value));
_ump[key] = _list.begin();
}
else
{
//没找到
if(_ump.size()>=_capacity)
{
_ump.erase(_list.back().first);
_list.pop_back();
}
_list.push_front(make_pair(key,value));
_ump[key] = _list.begin();
}
}
private:
list<pair<int, int>> _list;
int _capacity;
unordered_map<int, list<pair<int, int>>::iterator> _ump;
};