【Leetcode-146】LRU缓存机制(C++实现)


1 需求分析

需求
①O(1)时间访问任意key → 哈希表(unordered_map)
②O(1)时间删除LRU缓存中的键值对 → list
③O(1)时间向LRU缓存的头部增加/移动键值对 → list(不能使用vector,O(n)时间)

思路
外层数据结构:hashtable,存储键值对的键,值维护指向链表中元素的指针
内存数据结构:双向链表,支持O(1)时间插入/删除/移动操作

注:应尽量使用STL自带的容器/数据结构。

2 实现代码

#include <iostream>
using namespace std;
#include <list>
#include <unordered_map>

class LRUCache {
public:
    LRUCache(int capacity) {
        _capacity = capacity;
    }

    int get(int key) {
        //查询节点是否存在
        const auto pos = _map.find(key);

        if (pos == _map.end()) {    //关键字key不存在缓存中
            return -1;
        }
        else {  //关键字key存在缓存中,刚刚已被查询,则移至LRU缓存的最前位置(不会被最先删除)
            //list::splice(iterator position, list<T,Allocator>& x, iterator it); 
            //将链表对象x指定迭代器位置it的元素,拼接至position位置
            _cache.splice(_cache.begin(), _cache, pos->second);  //将节点移动至链表头
            return pos->second->second; //返回关键字key对应的值
        }

    }

    void put(int key, int value) {
        //判断待插入的键值对,关键字key是否已存在缓存中
        const auto pos = _map.find(key);

        if (pos != _map.end()) {    //关键字key已存在缓存中
            //更新对应的值
            pos->second->second = value;
            //将更新后的键值对,移至链表头
            _cache.splice(_cache.begin(), _cache, pos->second);
            return;
        }
        else {  //关键字key不存在缓存中
            //若插入前已到达缓存容量,删除链表末尾的节点(最近最久未使用)
            if (_cache.size() == _capacity) {
                //获取链表末尾的节点
                const auto& lastNode = _cache.back();
                //从哈希表中删除节点信息(根据关键字key删除)
                _map.erase(lastNode.first);
                //从链表中删除末尾节点
                _cache.pop_back();
            }

            //插入新的节点至链表头
            _cache.push_front(make_pair(key, value));
            //更新哈希表信息(关键字对应的值→链表的指针/迭代器位置)
            _map[key] = _cache.begin();
        }
    }

private:
    //缓存容量
    int _capacity;
    //存储键值对的链表(缓存)
    list<pair<int, int>> _cache;
    //哈希表-键和链表指针的映射关系 <关键字key, 链表元素的迭代器位置/指针>
    unordered_map<int, list<pair<int, int>>::iterator> _map;
};

/**
 * 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);
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值