设计LRU缓存

思路:

链接转载于https://blog.nowcoder.net/n/b279555a5cfd48f28fec790d96b0a1b9

代码:

//双向链表的一个节点:包含该节点的值,对应map的索引,每个节点都有一个前驱指针和一个后驱指针
struct Node{ 
    int key;
    int val;
    Node* pre;
    Node* next;
    //初始化
    Node(int k, int v): key(k), val(v), pre(NULL), next(NULL){}; 
};

class Solution {
public:
    int size = 0;
    //双向链表头尾
    Node* head = NULL; 
    Node* tail = NULL;
    //哈希表记录key值
    unordered_map<int, Node*> mp;
    //读入操作和容量
    vector<int> LRU(vector<vector<int> >& operators, int k) {
        vector<int> res;//用来记录get得到的值
        //构建初始化连接
        //链表剩余大小
        size = k; 
        head = new Node(0, 0);
        tail = new Node(0, 0);
        //将双向链表首尾相连
        head->next = tail;
        tail->pre = head;
        //操作数组为空,就直接返回
        if(operators.size() == 0) 
            return res;
        //遍历所有操作
        for(int i = 0; i < operators.size(); i++){ 
            auto op = operators[i];
            if(op[0] == 1) 
                //set操作
                set(op[1], op[2]);
            else if(op[0] == 2) 
                //get操作
                res.push_back(get(op[1]));
        }
        return res;
    }

    //插入函数
    void set(int key, int val){ 
        //没有见过这个key,新值加入
        if(mp.find(key) == mp.end()){ 
            Node* node = new Node(key, val);
            mp[key] = node;
            //超出大小,移除最后一个
            if(size <= 0) 
                removeLast();
            //大小还有剩余
            else 
                //大小减1
                size--; 
            //由于这个节点之前是不存在链表中的,所以要加到链表头
            insertFirst(node); 
        }
        //哈希表中已经有了,即链表里也已经有了
        else{  
            mp[key]->val = val;
            //访问过后,由于该节点原先已经存在在链表中,所以现在只需要将这个节点移到表头:在后面将这个节点去除后插入到表头
            moveToHead(mp[key]); 
        }
    }

    //获取数据函数
    int get(int key){ 
        //找不到返回-1
        int res = -1; 
        //哈希表中找到
        if(mp.find(key) != mp.end()){ 
            //获取
            res = mp[key]->val;
            //访问过后移到表头
            moveToHead(mp[key]); 
        }
        return res;
    }
    
    //移到表头函数
    void moveToHead(Node* node){ 
        //已经到了表头
        if(node->pre == head)  
            return;
        //将节点断开,取出来
        node->pre->next = node->next;
        node->next->pre = node->pre;
        //插入第一个前面
        insertFirst(node);
    }
    
    //将节点插入表头函数
    void insertFirst(Node* node){ 
        node->pre = head;
        node->next = head->next;
        head->next->pre = node;
        head->next = node;
    }
    
    //删去表尾函数,最近最少使用
    void removeLast(){ 
        //哈希表去掉key
        mp.erase(tail->pre->key);
        //断连该节点
        tail->pre->pre->next = tail; 
        tail->pre = tail->pre->pre;
    }
};