随笔 - 112  文章 - 0  评论 - 0  阅读 - 1352

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) 的平均时间复杂度运行。

 

示例:

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

 

 

复制代码
struct DLinkedNode{
    //变量
    int key,value;
    DLinkedNode* pre;
    DLinkedNode* next;
    //构造方法
    DLinkedNode(){
        this->key = 0;
        this->value =0;
        this->pre = nullptr;
        this->next = nullptr;
    }
    DLinkedNode(int _key,int _value){
        this->key = _key;
        this->value = _value;
        this->pre = nullptr;
        this->next = nullptr;
    }
};

class LRUCache {
private:
    map<int,DLinkedNode*> cache;  //键值与节点的映射
    int size; //链表实际长度
    int capacity;//链表容量
    DLinkedNode *head;//伪头结点
    DLinkedNode *tail;//伪尾节点
public:
    LRUCache(int capacity) {
        this->size = 0;
        this->capacity = capacity;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head->next = tail;
        tail->pre = head;
    }
    
    int get(int key) {
        if(!cache.count(key)){
            return -1;
        }else{//如果存在,放到头部,因为它是最近被访问的
            DLinkedNode* node = cache[key];
            moveToHead(node);
            return node->value;
        }
    }
    
    void put(int key, int value) {
        if(!cache.count(key)){//如果不存在,插入头部,并放进cache
            DLinkedNode* node = new DLinkedNode(key,value);
            cache[key] = node;
            addToHead(node);
            ++size;
            //如果超过容量,要删除末尾节点,因为它是最近最久未访问
            if(size>capacity){
                DLinkedNode* node = removeTail();
                cache.erase(node->key);
                delete node;
                --size;
            }
        }else{//如果存在,更新value并放到头部,因为它是最近被访问的
            DLinkedNode* node = cache[key];
            node->value = value;
            moveToHead(node);
        }
    }
    void moveToHead(DLinkedNode* node){
        removeNode(node);
        addToHead(node);
    }
    void removeNode(DLinkedNode* node){
        node->next->pre = node ->pre;
        node->pre->next = node->next;
    }
    void addToHead(DLinkedNode* node){
        head->next->pre=node;
        node->next = head->next;
        head->next = node;
        node->pre = head;
    }

    DLinkedNode* removeTail(){
        DLinkedNode* node = tail->pre;
        removeNode(node);
        return node;
    }

};

/**
 * 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);
 */
复制代码

 

posted on   _月生  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示