LRU 缓存(哈希表+双向链表)
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现
LRUCache
类:LRUCache(int capacity)
以 正整数 作为容量capacity
初始化 LRU 缓存int get(int key)
如果关键字key
存在于缓存中,则返回关键字的值,否则返回-1
。void put(int key, int value)
如果关键字key
已经存在,则变更其数据值value
;如果不存在,则向缓存中插入该组key-value
。如果插入操作导致关键字数量超过capacity
,则应该 逐出 最久未使用的关键字。
函数 get
和 put
必须以 O(1)
的平均时间复杂度运行。
示例:
输入 ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"] [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]] 输出 [null, null, null, 1, null, -1, null, -1, 3, 4] 解释 LRUCache lRUCache = new LRUCache(2); lRUCache.put(1, 1); // 缓存是 {1=1} lRUCache.put(2, 2); // 缓存是 {1=1, 2=2} lRUCache.get(1); // 返回 1 lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3} lRUCache.get(2); // 返回 -1 (未找到) lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3} lRUCache.get(1); // 返回 -1 (未找到) lRUCache.get(3); // 返回 3 lRUCache.get(4); // 返回 4
struct DLinkedNode{ //变量 int key,value; DLinkedNode* pre; DLinkedNode* next; //构造方法 DLinkedNode(){ this->key = 0; this->value =0; this->pre = nullptr; this->next = nullptr; } DLinkedNode(int _key,int _value){ this->key = _key; this->value = _value; this->pre = nullptr; this->next = nullptr; } }; class LRUCache { private: map<int,DLinkedNode*> cache; //键值与节点的映射 int size; //链表实际长度 int capacity;//链表容量 DLinkedNode *head;//伪头结点 DLinkedNode *tail;//伪尾节点 public: LRUCache(int capacity) { this->size = 0; this->capacity = capacity; head = new DLinkedNode(); tail = new DLinkedNode(); head->next = tail; tail->pre = head; } int get(int key) { if(!cache.count(key)){ return -1; }else{//如果存在,放到头部,因为它是最近被访问的 DLinkedNode* node = cache[key]; moveToHead(node); return node->value; } } void put(int key, int value) { if(!cache.count(key)){//如果不存在,插入头部,并放进cache DLinkedNode* node = new DLinkedNode(key,value); cache[key] = node; addToHead(node); ++size; //如果超过容量,要删除末尾节点,因为它是最近最久未访问 if(size>capacity){ DLinkedNode* node = removeTail(); cache.erase(node->key); delete node; --size; } }else{//如果存在,更新value并放到头部,因为它是最近被访问的 DLinkedNode* node = cache[key]; node->value = value; moveToHead(node); } } void moveToHead(DLinkedNode* node){ removeNode(node); addToHead(node); } void removeNode(DLinkedNode* node){ node->next->pre = node ->pre; node->pre->next = node->next; } void addToHead(DLinkedNode* node){ head->next->pre=node; node->next = head->next; head->next = node; node->pre = head; } DLinkedNode* removeTail(){ DLinkedNode* node = tail->pre; removeNode(node); return node; } }; /** * 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); */
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix