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

【数据结构与算法】LRUCache

实现LRUCache

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向z存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

// 结点类
struct Node {
    int key_, value_;
    Node *prev, *next;
    Node(int k = 0, int v = 0): key_(k), value_(v), prev(nullptr), next(nullptr) {}
};

class LRUCache {
public:
    int size_, cap_;
    Node *head, *tail;
    unordered_map<int, Node *> h;

    LRUCache(int capacity) {
        size_ = 0;
        cap_ = capacity;
        head = new Node();
        tail = new Node();
        head->next = tail;
        tail->prev = head;
    }
    
    int get(int key) {
        if(!h.count(key)) {
            return -1;
        } else { // 访问一个元素后,将其移动到头结点
            RemoveNode(h[key]);
            AddNodeToHead(h[key]);
            return h[key]->value_;
        }
    }
    
    void put(int key, int value) {
        if(h.count(key)) {
            RemoveNode(h[key]);
            AddNodeToHead(h[key]);
            h[key]->value_ = value;
        } else {
            if(size_ == cap_) { // LRU容量不够,删除链表尾元素
                h.erase(tail->prev->key_);
                RemoveNode(tail->prev);
                size_--;
            }
            h[key] = new Node(key, value);
            AddNodeToHead(h[key]);
            size_++;
        }
    }

    // 从双向链表中删除某个结点
    void RemoveNode(Node *node) {
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }

    // 将node插入到头结点之后
    void AddNodeToHead(Node *node) {
        node->prev = head;
        node->next = head->next;

        head->next->prev = node;
        head->next = node;
    }
};

http://www.kler.cn/a/387243.html

相关文章:

  • 【JVM】关于JVM的内部原理你到底了解多少(八股文面经知识点)
  • 《MYSQL45讲》误删数据怎么办
  • gdb编译教程(支持linux下X86和ARM架构)
  • TensorRT基础知识
  • activiti5基础和springboot整合
  • 金价大跌,特朗普胜选或成导火索
  • O-RAN Fronthual CU/Sync/Mgmt 平面和协议栈
  • 【系统集成项目管理工程师】英语词汇对照表-技术类
  • 大语言模型切分多头的多设备协同计算研究
  • 【GIS开发小课堂】高德地图+Three.js实现飞线、运动边界和炫酷标牌
  • go网络编程
  • lineageos-19 仓库群遍历,打印第一条git log
  • 【IEEE/EI会议】第八届先进电子材料、计算机与软件工程国际学术会议(AEMCSE 2025)
  • 初识TCP,实验加抓包带你理解为什么需要三次握手、四次挥手
  • 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-02
  • 高级java每日一道面试题-2024年10月30日-JVM篇-新生代垃圾回收器和老生代垃圾回收器有哪些?有什么区别?
  • ALU通常是双操作数结构
  • 数据库SQLite的使用
  • 在 CSS 中,gap 是 布局容器(flex 或 grid)的属性。它用于设置容器内子元素之间的间距。
  • D63【python 接口自动化学习】- python基础之数据库
  • 线性表(顺序表和链表)
  • C#入门 018 传值、输出、引用、数组、具名、可选参数、扩展方法(this)
  • 【Kafka:概念、架构与应用】
  • 【计算机视觉】深入浅出SLAM技术原理
  • 系统架构设计师论文:模型驱动架构设计方法及其应用
  • 【JAVA】Java基础—面向对象编程:类与对象-对象的创建