最近最少使用算法----LRU Cache

Posted 4nc414g0n

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近最少使用算法----LRU Cache相关的知识,希望对你有一定的参考价值。

LRU

LRU

概念:参考计算机系统课程
题目:146. LRU 缓存
要求:

  • 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
  • 实现 LRUCache 类:
  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存,int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。函数 get 和 put 必须以 O(1) 的平均时间复杂度运行

结构设计

要求均为O(1),第一选择就是hash+双链表
如果我们的设计是:

unordered__map<int, int> um;//key找value O(1)
list<pair<int, int>> li//头插头删尾插尾删O(1)

缺陷:新增是O(1),更新是O(N),要调整li中key的位置到头部,更新顺序但是我们不知道数据在哪,只能遍历查找,这个就是O(N)
关键:找到key的同时就找到其在li中的位置


使用迭代器:

typedef list<pair<int, int>>::iterator ListIter;
unordered_map<int, ListIter> um;
list<pair<int, int>> li;


只要找到key就能通过.find(),迭代器找到其在li的位置
代码:

class LRUCache 
public:
   LRUCache(int capacity) 
       :_capacity(capacity)
   

   int get(int key) 
       auto ret = um.find(key);
       if (ret != um.end())
       
           ListIter it = ret->second;
           //法1:erase 更新迭代器
          li.splice(li.begin(), li, it);//注意list的insert和splice均不会使迭代器失效
           return it->second;
       
       else
           return -1;
   

   void put(int key, int value) 
   
       //修改
       auto ret = um.find(key);
       if (ret == um.end())//无元素或li中不存在
       
           if (_capacity == li.size())
           
               auto back = li.back();
               um.erase(back.first);
               li.pop_back();
           
           li.push_front(make_pair(key, value));
           um[key] = li.begin();
       
       else //存在
       
           ListIter it = ret->second;
           it->second = value;
           li.splice(li.begin(), li, it);
       
       
   
private:
   typedef list<pair<int, int>>::iterator ListIter;
   unordered_map<int, ListIter> um;
   list<pair<int, int>> li;
   size_t _capacity;
;

注意

  • get逻辑找不到元素返回-1,找到需要将其置为li的首部操作:1.erase导致迭代器失效,需要自己控制,2.splice迭代器不会失效
  • put逻辑分1. 元素存在 2.元素不存在(注意判满)

以上是关于最近最少使用算法----LRU Cache的主要内容,如果未能解决你的问题,请参考以下文章

最近最少使用算法----LRU Cache

146 LRU Cache 最近最少使用页面置换算法

LRU cache

Cache替换算法:LRU与LFU的区别

Redis LRU Cache

如何用Redis做LRU-Cache