146. LRU 缓存

146. LRU 缓存

  1. 单向链表不遍历无法直接删除给定的节点
    双向链表因为:哈希表给出待操作的节点指针,需要delete或者moveToHead操作,单向链表无法获取该node的前向节点,删除该节点
  2. 链表节点需要key是因为:deleteTail之后,需要把哈希表中对应的key也给删了
// hashTable.begin()返回的是pair<int, Node*>,得用p->first和p->second访问
// delete P 导致"heap-use-after-free"大概率是链表的指针没连好
class CachedNode {
public:
    int key, value; 
    CachedNode * prev = NULL, * next = NULL;
    CachedNode():key(0), value(0){}
    CachedNode(int k, int v):key(k), value(v){}
};
class LRUCache {
private:
    int size = 0, cap;
    map<int, CachedNode*> cachedNodeMap;
    CachedNode * head, * tail;
public:
    LRUCache(int capacity) {
        cap = capacity;
        head = new CachedNode();
        tail = new CachedNode();
        // 1. 忘记给头尾节点接上了,光顾着生成两个节点了
        head->next = tail;
        tail->prev = head;
    }
    int get(int key) {
        // 还可以用cachedNodeMap.find(key) != cachedNodeMap.end()来判断
        if (cachedNodeMap.count(key) == 0) return -1;
        int val = cachedNodeMap[key]->value;
        moveToHead(cachedNodeMap[key]);
        return val;
    }
    void put(int key, int value) {
        // 2.一定要分情况,按照“已经存在这个key”,“未存在”区分
        if (cachedNodeMap.count(key) > 0) {
            moveToHead(cachedNodeMap[key]);
            cachedNodeMap[key]->value = value;
            return;
        } 
        CachedNode * newCachedNode = new CachedNode(key, value);
        addToHead(newCachedNode);
        // 3.漏掉把key加到map上了
        cachedNodeMap[key] = newCachedNode;
        size++;
        if (size > cap) {
            // 4.这里之前在deleteTail()里面直接erase的key,最好提出来写,要不有的map操作在外面,有的在里面,容易出错
            // 千万不能在deleteTail里面erase,尤其put没区分是否存在的写法,因为put是先hashTable[key] = val,如果出现 2 1 2在这删的时候就把刚加进来的map给删了
            cachedNodeMap.erase(tail->prev->key);
            deleteTail();
            size--;
        }
    }

    void moveToHead(CachedNode * node) {
        node->prev->next = node->next;
        node->next->prev = node->prev;
        addToHead(node);
    }

    void addToHead(CachedNode * node) {
        head->next->prev = node;
        //5. 这里写错了, head->next多写成了head->next->prev
        node->next = head->next;
        head->next = node;
        node->prev = head;
    }

    void deleteTail() {
        CachedNode * deleteNode = tail->prev;
        tail->prev = tail->prev->prev;
        //6. 上面一行都给tail->prev->prev改了,怎么能还用这个呢 tail->prev->prev->next = tail;
        tail->prev->next = tail;
        delete deleteNode;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值