Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
题意
设计一个数据结构实现LRU算法。支持get和set操作。
get 获取key对应的value值,如果没有这个key则返回-1;
set 给key赋value的值,如果key不存在则插入key-value对; 当缓存满了的时候,删除最近最少使用的键值对,然后再插入新的键值对之。
题解
LRU是一种应用在操作系统上的缓存替换策略,和我们常见的FIFO算法一样,都是用于操作系统中内存管理中的页面替换,其全称叫做Least Recently Used(近期最少使用算法),算法主要是根据数据的历史访问记录来进行数据的淘汰,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
为了能够比较形象的了解LRU的执行过程,我们举一个例子,如下:
假定现有一进程的页面访问序列为:
4,7,0,7,1,0,1,2,1,2,6
缓存容量为5,则随着进程的访问,缓存栈中页面号的变化情况如下图所示。在访问页面6时发生了缺页,此时页面4是最近最久未被访问的页,应将它置换出去。
如此,使用双链表是最好实现数据操作的数据结构了。因为数据被访问的时候需要把这个数据移到链表最前面,这样最近没有被访问的数据将处于链表的最后面。如图:
查找的话还需要hashmap这个数据结构。
class LRUCache{
public:
LRUCache(int capacity) {
m_capacity=capacity;
}
int get(int key) {
int res=-1;
auto it =cache_map.find(key);
if(it!=cache_map.end())
{
res=it->second->second;
list<pair<int,int> > ::iterator temp_list=it->second;
pair<int,int> temp_pair=*temp_list;
cache.erase(temp_list);
cache.push_front(temp_pair);
cache_map[key]=cache.begin();//更新map中 链表键值对的指针
}
return res;
}
void set(int key, int value) {
auto it =cache_map.find(key);
if(it!=cache_map.end())
{
list<pair<int,int> > ::iterator temp_list=it->second;
temp_list->second=value;
pair<int,int> temp_pair=*temp_list;
cache.erase(temp_list);
cache.push_front(temp_pair);
cache_map[key]=cache.begin();//更新map中 链表键值对的指针
}
else
{
pair<int,int> temp_pair=make_pair(key,value);
if(m_capacity==cache.size())
{
int old_key=cache.back().first;
cache.pop_back();
auto del =cache_map.find(old_key);
cache_map.erase(del);
}
cache.push_front(temp_pair);
cache_map[key]=cache.begin();//更新map中 链表键值对的指针
}
}
private:
int m_capacity;
list<pair<int,int> > cache;
map< int, list<pair<int, int> > :: iterator> cache_map;
};