146. LRU 缓存

146. LRU 缓存

  1. 超时的思路
class Node {
public:
    int val;
    int key;
    Node * pre, * next;
    Node(int k,int v):val(v), key(k), pre(NULL), next(NULL){}
    Node():pre(NULL), next(NULL){}
};

class LRUCache {
private:
    // 5.bug. 类的成员变量必须初始化,因为是放在栈中的,size不初始化就是个负无穷,永远都不可能大于capcitity
    int cap, size = 0;
    Node * head, *p, *tail;
    unordered_map<int, Node*> cache;
public:
    LRUCache(int capacity) {
        cap = capacity;
        head = new Node();
        tail = new Node();
        head->next = tail;
        tail->pre = head;
    }
    
    int get(int key) {
        if (cache.count(key) == 0) return -1;
        p = cache[key];
        deleteNode(p);
        addToHead(p);
        //printNodeList();
        // 1.bug. 在输出链表的时候把p移动了,回来又用移动之后的返回,尽量能用局部变量就用局部叭,全局的说不定哪一糊涂就给改了。
        return p->val;
    }

    
    void put(int key, int value) {
        Node * now = new Node(key, value);
        // 4.bug. 判断hash表中是否已经存在该元素,!用反了
        if (cache.count(key) != 0) {
            // 2.bug. 开始为了减少冗余代码,把addToHead放到了if外面,虽然两块的addToHead都会执行,但由于先执行了它,改变了判断条件,导致进入了不同的if逻辑
            // 6.bug. 开始的时候先delete在add的,add和delete里面都有对cache的操作,add之后delete就会把cache的记录一起干掉,对全局变量的操作还是拿出来比较好。
            deleteNode(cache[key]);
            addToHead(now);
            cout<<"++++cache[key]  "<<cache[key]->key<<endl;
            
            return;
        }
        addToHead(now);
        if (size > cap) {
            deleteNode(tail->pre);
        }
        printNodeList();
    }

    void addToHead(Node * now) {
        head->next->pre = now;
        now->next = head->next;
        head->next = now;
        now->pre = head;
        cache[now->key] = now;
        size++;
    }

    void deleteNode(Node * now) {
        now->pre->next = now->next;
        now->next->pre = now->pre;
        // 3.bug map删除一个元素用erase,肯定和数组写哈希表不能混用,不能用cache[key] = NULL,这样的话,查找的时候是能查找到元素的
        cache.erase(now->key);
        size--;
    }
};

上一篇:java实现LRU缓存


下一篇:Python funtools 中的 lru_cache 和 singledispatch