LRU缓存实现

发布时间 2023-09-24 18:34:58作者: 失控D大白兔

一. LRU缓存实现

使用双向链表保证O(1)的优先度更改,同时当做优先队列维护插入顺序
同时这里要结合哈希表,保证更改想要的节点

/*
定义Node 双向链表节点
定义 remove 进行删除节点(只删除节点在链表中的关系)
定义 update 更新指定节点的优先度
定义 insert 插入新的节点
*/


class LRUCache {
public:
    typedef struct Node {//双向链表
        int key;//在哈希中的键值,用于删除哈希
        int data;
        Node* pre;
        Node* next;
        Node() :  key(0), data(0), pre(nullptr), next(nullptr) {}
        Node(int key,int val) :key(key), data(val), pre(nullptr), next(nullptr) {}
    }Node,*pNode;

    int capacity;
    unordered_map<int,pNode> m;
    Node* listpre = new Node();
    Node* listtail = new Node();

    void remove(Node* cur){
        //更改节点关系
        Node* pre = cur->pre;
        Node* next = cur->next;
        pre->next = next;
        next->pre = pre;
    }
    void update(Node* cur){ //更新时间,就是把节点移到最后面,同时更改前后节点关系
        //更改节点关系
        remove(cur);
        //移动到最后面
        insert(cur);
    }
    void insert(Node* cur){ //插入缓存,就是把节点放到最后面
        listtail->pre->next = cur;
        cur->pre = listtail->pre;
        cur->next = listtail;
        listtail->pre = cur;
    }

    void release(){//清除内存,就是从链表头部删除节点,同时也要删除索引
        Node* cur = listpre->next;
        m.erase(cur->key);//删除索引
        remove(cur);
    }

    //要有个结构记录最近最久未使用,使用有序结构即可
    //访问后,如何对优先度进行更新,可以用哈希+链表,把指定节点剔除移到最后
    LRUCache(int capacity) {
        this->capacity = capacity;
        //初始化双向链表结构
        listpre->next  = listtail;
        listtail->pre = listpre;
    }
    
    int get(int key) {
        //这里首先判断是否存在
        if(m.count(key)==0) return -1;
        //存在则进行更新时间
        update(m[key]);
        return m[key]->data;
    }
    
    void put(int key, int value) {
        //首先判断是否存在,存在则进行更新
        if(m.count(key)){
            m[key]->data = value;//更新值
            //更新优先度
            update(m[key]);
            return;
        }
        //不存在进行插入
        if(m.size()==capacity) 
            release();//内存不够,释放一个节点
        Node* cur = new Node(key,value);
        m[key] = cur;//建立索引
        insert(cur);
    }
};