【C++实现LRU缓存】

7 篇文章 0 订阅

LRU缓存机制

题目:leetcode
题解
LRU缓存机制: Least Recently Used,缓存大小超过容量大小时,将最近最少使用的数据淘汰
解决思路:哈希表+双向列表;哈希表为普通的哈希影射,存储key和value;双向列表按顺序存储键值对,头部键值最近使用,尾部最久未使用

#include <iostream>
#include <unordered_map>
#include <string>
#include <memory>

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

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

class LRUCache {
private:
  std::unordered_map<int, DListNode*> cache;  // 哈希表+双向列表 缓存map
  DListNode *head, *tail;
  int size;
  int capacity;
public:
  LRUCache(int capacity) {
    this->capacity = capacity;
    this->size = 0;
    head = new DListNode();
    tail = new DListNode();
    head->next = tail;
    tail->pre = head;
  }
  
  int get(int key) {
    if (!cache.count(key)) return -1; // key不存在
    // key存在,先通过哈希表定位,再将key所在的结点移到双向列表头部
    DListNode *node = cache[key];
    MoveToHead(node);
    return node->val;
  }
  
  void put(int key, int value) {
    if (!cache.count(key)) {
      // key 不存在,创建node以及新的map键值对,并将node移到双向列表头部
      DListNode *node = new DListNode(key, value); 
      cache[key] = node;
      AddToHead(node);
      ++size;
      if (size > capacity) {
        // 超过缓存容量,需要删除双向列表的尾部结点
        DListNode *remove_node = RemoveTailNode();
        cache.erase(remove_node->key);
        delete remove_node;   // 防止内存泄露
        --size;
      }
    } else {
      // 如果key存在,先通过哈希表定位,然后修改val值,并将node移到双向列表头部
      DListNode *node = cache[key];
      node->val = value;
      MoveToHead(node);
    }
  }
private:
  void RemoveNode(DListNode *node) {  // node->pre node node->next
    node->pre->next = node->next;
    node->next->pre = node->pre;
  }
  void MoveToHead(DListNode *node) {
    RemoveNode(node);
    AddToHead(node);
  }
  void AddToHead(DListNode *node) { // head node head->next  相当于将node插入head和head->next之间
    node->pre = head;
    node->next = head->next;
    head->next->pre = node;
    head->next = node;
  }
  DListNode* RemoveTailNode() {
    DListNode *tail_node = tail->pre;
    RemoveNode(tail_node);
    return tail_node;
  }
};


int main(int args, char **argv) {
  std::cout << "hello lch" << std::endl;
  std::shared_ptr<LRUCache> lru_cache = std::make_shared<LRUCache>(2);
  lru_cache->put(1, 1); // 缓存是 {1=1}
  lru_cache->put(2, 2); // 缓存是 {1=1, 2=2}
  std::cout << lru_cache->get(1) << std::endl;    // 返回 1
  lru_cache->put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
  std::cout << lru_cache->get(2) << std::endl;    // 返回 -1 (未找到)
  lru_cache->put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
  std::cout << lru_cache->get(1) << std::endl;    // 返回 -1 (未找到)
  std::cout << lru_cache->get(3) << std::endl;    // 返回 3
  std::cout << lru_cache->get(4) << std::endl;    // 返回 4

  std::cout << "end lch" << std::endl;
  return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自动驾驶小哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值