-
请你设计并实现一个满足 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) 的平均时间复杂度运行。
-
以下是一个简单的LRU(最近最少使用)缓存实现,使用C++语言实现。
#include <iostream>
#include <unordered_map>
#include <list>
using namespace std;
class LRUCache {
public:
LRUCache(int capacity) {
_capacity = capacity;
}
int get(int key) {
auto it = _cache.find(key);
if (it == _cache.end()) {
// key不存在
return -1;
}
// key存在,将其移到链表头部
_list.splice(_list.begin(), _list, it->second);
return it->second->second;
}
void put(int key, int value) {
auto it = _cache.find(key);
if (it != _cache.end()) {
// key已存在,更新值,将其移到链表头部
it->second->second = value;
_list.splice(_list.begin(), _list, it->second);// 将it->second[param3] of _list[param2] in front of _list.begin()[param1]
return;
}
if (_cache.size() == _capacity) {
// 缓存已满,删除链表尾部元素和缓存中的对应项
int key_to_del = _list.back().first;
_list.pop_back();
_cache.erase(key_to_del);
}
// 将新元素插入链表头部和缓存中
_list.emplace_front(key, value);// 注:emplace_*() 函数在原理上比 push_*() 有内存优化方面和运行效率方面的优化。
_cache[key] = _list.begin();
}
private:
int _capacity;
list<pair<int, int>> _list;
unordered_map<int, list<pair<int, int>>::iterator> _cache;
};
int main() {
LRUCache cache(2);
cache.put(1, 1);
cache.put(2, 2);
cout << cache.get(1) << endl; // 返回 1
cache.put(3, 3); // 该操作会使得关键字 2 作废
cout << cache.get(2) << endl; // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得关键字 1 作废
cout << cache.get(1) << endl; // 返回 -1 (未找到)
cout << cache.get(3) << endl; // 返回 3
cout << cache.get(4) << endl; // 返回 4
return 0;
}
-
这个实现使用了一个双向链表来维护缓存中元素的顺序,链表头部表示最近使用的元素,链表尾部表示最久未使用的元素。同时,还使用了一个哈希表来快速查找缓存中的元素。
-
当要访问缓存中的某个元素时,先在哈希表中查找该元素是否存在,如果存在,将其移到链表头部并返回值;如果不存在,返回-1。当要往缓存中加入新元素时,如果缓存已满,先删除链表尾部元素和哈希表中的对应项,然后将新元素插入链表头部和哈希表中;如果缓存未满,直接将新元素插入链表头部和哈希表中即可。