当前位置: 首页 > article >正文

LRU算法

LRU算法

前言:

我们常用缓存提升数据查询速度,由于缓存的容量有限,当达到上限的时候,就需要删除部分数据挪出空间,这样新的数据才可以添加进来,缓存数据不能随机删除,一般情况下需要根据某种特定的算法删除缓存数据,常用的淘汰算法右LRU,LFU,FIFO

核心思想:如果数据最近被访问过,那么是热门数据,下次很大概率会再次被使用。如果内存满了,有限淘汰最近很少使用的数据

LRU: Least Recently Used, 最近最少使用,主要应用场景是缓存,缓存规则如下。

①.最近被使用或访问的数据放置在最前面;
②.没当缓存命中(即缓存数据被访问)则将数据移到头部;
③.当缓存数量达到最大值时,将最近最少访问的数据剔除;

  • 访问一个数据,哪个数据就会被添加到头节点。
class Node { // 双向链表的节点
public:
    int key;    // key值是为了便于哈希表的定位
    int value;  // 缓存的数据
    Node* prev; // 前驱指针
    Node* next; // 后驱指针
    // 构造函数
    // 给一个默认参数key为0,v为0
    Node(int k = 0, int v = 0) : key(k), value(v) {}
};

class LRUCache {
private:
    int capacity; // 缓存的容量
    Node* dummy;  // 哨兵节点,双向链表的头节点
    unordered_map<int, Node*> key_to_node;
    // 哈希表,存储key和node的信息
public:
    // 构造函数
    LRUCache(int capacity) : capacity(capacity), dummy(new Node()) {
        dummy->prev = dummy;
        dummy->next = dummy;
    }

    // 删除一个节点(抽出一本书)
    // 双向链表的删除节点
    void remove(Node* x) {
        x->prev->next = x->next; // 前面的后继要改
        x->next->prev = x->prev; // 后面的前驱要改
    }

    // 在链表头添加一个节点(把一本书放在最上面)
    // 双向链表的头插
    void push_front(Node* x) {
        x->next = dummy->next; // 1
        dummy->next = x;       // 4
        x->prev = dummy;       // 2
        x->next->prev = x;     // 3
        // 4一定要在1的后面,其他的顺序随意,绑线原则
    }

    Node* get_node(int key) {
        auto it = key_to_node.find(key);
        if (it == key_to_node.end()) // 没有这本书
            return nullptr;
        auto node = it->second; // 有这本书
        remove(node);           // 把这本书抽出来
        push_front(node);       // 放在最上面
        return node;            //返回这本书
    }

    int get(int key) {
        auto node = get_node(key);
        //如果node不为空,就返回node的value
        //如果为空,就是-1
        return node ? node->value : -1;
    }

    void put(int key, int value) {
        auto node = get_node(key);//获取node
        //node不为空,就是有这本书
        if (node) {              // 有这本书
            node->value = value; // 更新 value
            return;
        }
        node = new Node(key, value); // 新书
        key_to_node[key] = node;
        push_front(node);                               // 放在最上面

        //超过容量
        if (key_to_node.size() > capacity) {            // 书太多了
            auto back_node = dummy->prev;//头节点的前驱放的是最后一个节点
            key_to_node.erase(back_node->key);
            remove(back_node); // 去掉最后一本书
            delete back_node;  // 释放内存
        }
    }
};


http://www.kler.cn/news/362564.html

相关文章:

  • 落实“双碳”行动,深兰科技推动分子能源技术在AI硬件产品领域的应用及产业化进程
  • 一款好用的搜索软件——everthing(搜索比文件资源管理器快)
  • 在linux上安装r-base和rpy2到conda环境
  • 什么是分库分表?为什么要分库分表?什么时候需要分库分表?怎么样拆分?(数据库分库分表详解)
  • Java:抽象类和接口
  • 房屋租赁网站毕业设计基于SpringBootSSM框架的计算机毕业设计
  • ATmega128定时器里面的定时器和外部中断配置
  • ElasticSearch基本概念
  • 微软主动出击,“钓”出网络钓鱼者
  • 关于在ubuntu服务器上无法守护长链接命令的问题
  • 自动化数据库管理:如何通过存储过程动态创建 MySQL 对象
  • Python中的字符串修剪:strip()、lstrip() 和 rstrip()
  • 1U服务器和Hyper-V虚拟机使用记录
  • [Linux网络编程]06-I/O多路复用策略---select,poll分析解释,优缺点,实现IO多路复用服务器
  • 设计模式基础知识以及典型设计模式总结(上)
  • Spring Boot驱动的汽车销售网站架构优化
  • ansible playbooks
  • 关于WPF项目降低.Net版本
  • Unity性能优化2【脚本篇】
  • 电脑改ip地址怎么弄?一键操作与多种方法详解
  • 存储过程(SQL)
  • (3) c++基本代码
  • CF-Loss:用于视网膜多分类血管分割和血管特征测量的临床相关特征优化损失函数|文献速递-基于生成模型的数据增强与疾病监测应用
  • 储能电站箱变:绿色能源优化的关键设备
  • 2024 睿抗机器人开发者大赛(RAICOM)-【网络安全】CTF 部分WP
  • 96. 正投影相机-Canvas尺寸变化