实现LRU缓存策略

LRU缓存策略

英文全称Least Recently Used,是页面置换算法的一种,即淘汰掉最长时间不使用的页面。
在缓存中,是一种缓存淘汰策略,优先删除很久没有用过的数据。

实现思路分析

设计put和get方法,实现O(1)时间的查找插入删除,应该用散列表;但散列表是无序的,要实现有序性,应该用链表结构。因此,一个哈希链表的结构符合我们的要求。

实现代码

题目来源:LeetCode 146
解法来源:LeetCode用户 labuladong

  • 所需的数据结构(双向链表)
    //双向链表
    struct Node{
      size_t  key, val;
      Node* next;
      Node* pre;
      Node(size_t k, size_t v): key(k), val(v), next(nullptr), pre(nullptr) {}    
    };
  • 双向链表需要的一些接口函数
    class DoubleList{
    private:
      Node head, tail;  //头尾哨兵节点
      size_t  size;  //链表长度
    public:
      //新建双向链表
      DoubleList(){
          head = new Node(0,0);
          tail = new Node(0,0);
          head->next = tail;
          tail->pre = head;
          size = 0;
      }
      //在头部添加节点
      void addToHead(Node n){
          Node* temp = head->next;
          n->next = temp;
          temp->pre = n;
          n->pre = head;
          head->next = x;
          size++;
      }
      //删除链表中n节点
      void deleteNode(Node n){
          Node* temp = n->next;
          n->pre->next = temp;
          temp->pre = n->pre;
          size--;
          delete n;
      }
      //删除链表最后一个节点并返回
      Node* deleteLast(){
          if(tail->pre==head) return nullptr;
          Node* last = tail->pre;
          last->pre->next = tail;
          tail->pre = last->pre;
          delete last;
          return last;
      }
      size_t getSize(){
          return size;
      }
    };
  • 实现逻辑
    size = 2 容量大小为2
    put(1,1),put(2,2); 把1和2 放进缓存中
    get(1,1) return 1; 查找1,找到返回1;
    put(3,3); 此时废除2
    get(2,2) return -1; 2已被废除,找不到返回-1
    LRUCache(int capacity) {
      }
    //key和Node映射
    unordered_map<size_t k, Node* pNode> hashmap;
    DoubleList cache;
    int get(int key){
      //没找到返回-1
      if(hashmap.find(key)==hashmap.end())  return -1;
      //找到了就把数据提到开头
      else{
          cache.addToHead(hashmap[key]);
          return hashmap[key]->val;
      }
    }
    int put(int key, int val){
      Node x = new Node(key, val);  //新插入的节点 x
      //如果插入的key已经存在就把旧的数据删除再插入,不存在就直接插入即可
      if(hashmap.find(key)!=hashmap.end()){
          cache.delete(hashmap[key]);
          cache.addToHead(x);
      }
      else{
          //如果cache满了,那就删除链表最后一个位置
          if(cache.getSize()==capcity){
              cache.deleteLast();
          }
          cache.addToHead(x);
          hashmap[key] = x;
      }
    }        

    C++解法(list+unordered_map)

    class LRUCache {
    private:
      int cap;
      list<pair<int, int>> cache;  //双向链表
      unordered_map<int key, list<pair<int, int>::iterator> > hashmap;
    }
    public:
      LRUCache(int capacity) {
          this->cap = capacity; 
      }
      int get(int key){
          auto it = hashmap[key];
          if(it==hashmap.end()) return -1;  //没找到
          pair<int, int> kv = *hashmap[key];
          cache.erase(map[key]);
          cache.push_front(kv);
          hashmap[key] = cache.begin();  //map中存的是迭代器,注意这一点!!
          return kv.second;
      }
      void put(int key, int value){
          auto it = hashmap[key];
          if(it==hashmap.end()){
              if(cache.size()==cap){
                  auto lastPair = cache.back();
                  map.erase(lastPair.first);
                  cache.pop_back();
              }
              cache.push_front(make_pair<key, value>);
              hashmap[key] = cache.begin();
          }
          else{
              cache.erase(map[key]);
              cache.push_front(make_pair<key, value>);
              hashmap[key] = cache.begin();
          }
      }
    };            
全部评论

相关推荐

02-01 12:05
复旦大学 Java
腾讯的提前批大概率应该是没有笔试的,但是这个时候有相当部分的同学简历估计都没有准备好,没准备好的同学也不用急,大部分都是3月之后开,这个时候开的绝大多数都是神仙打架,问的东西也比较难,打算投递的同学也多看下计算机网络和操作系统,腾讯对这部分的知识问的比较多。另外多刷下牛客的热门题库,刷题注意刷ACM模式,和牛客的周赛题,腾讯有的部门会从这里面出原题。我是@程序员花海关注我,带你了解更多校招资讯!
程序员花海:还没有来得及准备的同学可以看下学习路线:https://www.nowcoder.com/discuss/824693499982315520?sourceSSR=users算法题:https://www.nowcoder.com/feed/main/detail/20e7a999fa04485b88340a274411ca0d?sourceSSR=users八股文:https://www.nowcoder.com/discuss/833102362771251200?sourceSSR=users简历书写方式:https://www.nowcoder.com/discuss/839907820706205696?sourceSSR=users都是以前在牛客发的文章~
软开人,秋招你打算投哪些...
点赞 评论 收藏
分享
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
01-07 00:20
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务