欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > LRU缓存

LRU缓存

2024/12/21 23:47:17 来源:https://blog.csdn.net/weixin_73809064/article/details/144424195  浏览:    关键词:LRU缓存

一、概念

LRU缓存(Least Recently Used Cache)是一种常用的缓存淘汰算法,它基于“最近最少使用”的原则来管理缓存中的数据对象。当缓存空间不足时,LRU缓存会淘汰最久未被使用的数据,以确保缓存中始终存储着最新和最频繁使用的数据。

二、基本原理

LRU缓存的核心思想是:最近被访问的数据在未来可能会被再次访问,因此应该保留最近被访问的数据,淘汰最久未使用的数据。具体来说,LRU通过以下步骤工作:

  1. 缓存访问:当一个数据被访问时,算法会记录这个数据的访问时间或更新其访问顺序。
  2. 缓存插入:当需要将新数据插入缓存时,如果缓存尚未满,则直接插入。如果缓存已满,则使用LRU策略淘汰最久未使用的数据。
  3. 缓存淘汰:依据LRU策略,淘汰那些最久未被使用的数据,即那些距离上次访问时间最长的缓存项。

三、双向链表+哈希表实现

链表结点:

存储key的原因是缓存淘汰时可以获取到淘汰结点的key,从而删除哈希表中对应的值。

 使用双向链表的原因是单向链表无法获取前一个元素,无法只通过结点指针删除该结点。

struct mListNode
{int key;int value;struct mListNode *next;struct mListNode *pre;mListNode():key(0),value(0),next(nullptr),pre(nullptr){}mListNode(int k,int v):key(k),value(v),next(nullptr),pre(nullptr){}
};

双向链表:

在双向链表的实现中,使用一个伪头部(dummy head)和伪尾部(dummy tail)标记界限,这样在添加节点和删除节点的时候就不需要检查相邻的节点是否存在。

缓存访问:moveToTail

缓存插入:addToTail,再判断是否超出capacity,若超过则缓存淘汰

缓存淘汰:removeOldest从表头移除元素

class DLinkedList
{
public:DLinkedList():_head(new mListNode),_tail(new mListNode),_size(0){_head->next=_tail;_tail->pre=_head;}mListNode *addToTail(int key,int value){mListNode *pNew=new mListNode(key,value);pNew->next=_tail;pNew->pre=_tail->pre;_tail->pre->next=pNew;_tail->pre=pNew;++_size;return pNew;}void removeElem(mListNode *p){p->pre->next=p->next;p->next->pre=p->pre;delete p;p=nullptr;--_size;}int removeOldest(){int key=_head->next->key;removeElem(_head->next);return key;}void show()//调试用{if(_size==0) return;mListNode *cur=_head->next;while(cur->next){cout<<cur->key<<":"<<cur->value<<" ";cur=cur->next;}cout<<"\n";}void moveToTail(mListNode *p){p->pre->next=p->next;p->next->pre=p->pre;p->next=_tail;p->pre=_tail->pre;_tail->pre->next=p;_tail->pre=p;}int size() const{return _size;}
private:mListNode *_head;mListNode *_tail;int _size;
};

 LRU缓存:

class LRUCache {
public:unordered_map<int,mListNode*> cache;int cap;DLinkedList *list;
public:LRUCache(int capacity):cap(capacity),list(new DLinkedList()){}int get(int key) {if(!cache.count(key)){return -1;}mListNode *p=cache[key];list->moveToTail(p);return p->value;}void put(int key, int value) {if(cache.count(key)){mListNode *p=cache[key];p->value=value;list->moveToTail(p);}else{mListNode *p=list->addToTail(key,value);cache[key]=p;}while(cap<list->size()){int key=list->removeOldest();cache.erase(key);}}
};

四、使用std::list+std::unordered_map实现 

class LRUCache {
public:unordered_map<int,std::list<pair<int,int>>::iterator> cache;int cap;list<pair<int,int>> list;
public:LRUCache(int capacity):cap(capacity),list(){}int get(int key) {if(!cache.count(key)){return -1;}auto it=cache[key];list.splice(list.begin(),list,it);return it->second;}void put(int key, int value) {if(cache.count(key)){auto it=cache[key];it->second=value;list.splice(list.begin(),list,it);cache[key]=list.begin();}else{list.push_front(make_pair(key,value));cache[key]=list.begin();}while(cap<list.size()){auto it=list.back();list.pop_back();cache.erase(it.first);}}
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com