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的主要内容,如果未能解决你的问题,请参考以下文章

LRU Cache

LRU Cache

LRU Cache

LRU Cache

3-3存储系统-高速缓冲存储器Cache

LRU算法原理解析