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

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.元素不存在(注意判满)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值