LRU Cache
Posted qnbk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LRU Cache相关的知识,希望对你有一定的参考价值。
LRU Cache
LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法。
Cache:狭义的Cache指的是位于CPU和主存间的快速RAM, 通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。 广义上的Cache指的是位于速度相差较大的两种硬件之间, 用于协调两者数据传输速度差异的结构。除了CPU与主存之间有Cache, 内存与硬盘之间也有Cache,乃至在硬盘与网络之间也有某种意义上的Cache── 称为Internet临时文件夹或网络内容缓存等。
Cache的容量有限,因此当Cache的容量用完后,而又有新的内容需要添加进来时, 就需要挑选并舍弃原有的部分内容,从而腾出空间来放新内容。LRU Cache 的替换原则就是将最近最少使用的内容替换掉。
其实,LRU译成最久未使用会更形象, 因为该算法每次替换掉的就是一段时间内最久没有使用过的内容。
LRU Cache的实现
保持高效实现O(1)的put和get,那么使用双向链表和哈希表的搭配是最高效和经典的。使用双向链表是因为双向链表可以实现任意位置O(1)的插入和删除,使用哈希表是因为哈希表的增删查改也是O(1)。
把最近最少用的从头开始依次排序
class LRUCache
typedef list<pair<int,int>>::iterator LRU_list_it;
typedef list<pair<int,int>> LRU_list;
public:
LRUCache(int capacity)
_capacity = capacity;
int get(int key)
// 如果key对应的值存在,则listit取出,这里就可以看出hashmap的value存的是list的
iterator的好处:找到key
// 也就找到key存的值在list中的iterator,也就直接删除,再进行头插,实现O(1)的数据挪
动。
auto mit = _kitmap.find(key);
if(mit == _kitmap.end())
return -1;
else
//拿到value
LRU_list_it Ltit = mit->second;
int val = Ltit->second;
//调整LRU顺序
_kvlt.splice(_kvlt.end(),_kvlt,Ltit);
return val;
void put(int key, int value)
auto mit = _kitmap.find(key);
if(mit == _kitmap.end())
/*
//1如果key不在cache,其容量不满,直接插入
if(_kvlt.size() < _capacity)
_kvlt.push_back(make_pair<key,value>);
_kitmap[key] = --_kvlt.end();
else
//2\\如果key不在cache,其容量慢了,需要先删除LRU头部数据再插入
_kitmap.erase(_kvlt.front().first);
_kvlt.pop_back();
_kitmap.push_back(make_pair(key,value));
_kitmap[key] = --_kvlt.end();
*/
if(_kvlt.size() >= _capacity)
//容量不够
_kitmap.erase(_kvlt.front().first);
_kvlt.pop_front();
_kvlt.push_back(make_pair(key,value));
_kitmap[key] = --_kvlt.end();
else
//更新value
LRU_list_it Ltit = mit->second;
Ltit->second = value;
//调整LRU顺序
//转移方法
_kvlt.splice(_kvlt.end(),_kvlt,Ltit);
private:
LRU_list _kvlt;
unordered_map<int,LRU_list_it> _kitmap;
//get(k)的时候拿到的数据kv在list中存的位置的迭代器,
//既可以拿到value,又可以调整list结点的顺序位置O(1)
int _capacity;//记录容量
;
以上是关于LRU Cache的主要内容,如果未能解决你的问题,请参考以下文章