原题链接:Leetcode 146. LRU 缓存
LRU(Least Recently Used,最近最少使用)缓存是一种内存数据管理策略,核心思想是:当缓存空间满时,优先淘汰 "最近一段时间内最少被访问" 的数据,为新数据腾出空间。它的设计目标是利用 "局部性原理"(程序或用户访问数据时,往往会在短时间内重复访问同一批数据),尽可能保留高频访问的数据,从而减少对底层存储(如数据库、硬盘)的依赖,提升数据读取效率。
LRU 的行为围绕 "访问" 和 "淘汰" 两个关键场景展开:
- 数据访问时(读 / 写):
- 若数据已在缓存中("命中"),则将其标记为 "最近使用过"(更新它的访问优先级,避免被优先淘汰);
- 若数据不在缓存中("未命中"),则将其存入缓存;若缓存已满,先淘汰 "最久未访问" 的数据,再存入新数据。
- 缓存满时淘汰:
严格选择 "最近一段时间内没有被访问过" 或 "访问频率最低" 的数据进行删除。
LRU 的高效实现需要满足两个核心需求:
- 快速查找数据(判断是否在缓存中)
- 快速更新 / 删除数据(调整访问优先级、淘汰旧数据)
- 经典实现采用 "哈希表 + 双向链表" 的组合
代码参考官解:LRU缓存机制
cpp
// 设计一个双向链表结构体
struct Node{
int key,value;
Node* prev;
Node* next;
Node():key(0),value(0),prev(nullptr),next(nullptr) {};
Node(int k,int v):key(k),value(v),prev(nullptr),next(nullptr) {};
};
class LRUCache {
private:
int size;
int capacity;
Node* head;
Node* tail;
unordered_map<int,Node*> cache;
public:
LRUCache(int _capacity): capacity(_capacity),size(0) {
head = new Node();
tail = new Node();
head->next = tail;
tail->prev = head;
}
int get(int key) {
// 如果在当前缓存内没有找到
if(!cache.count(key)){
return -1;
}
// 如果找到
Node* node = cache[key];
move_to_head(node);
return node->value;
}
void put(int key, int value) {
// 如果在当前缓存内没有找到
if(!cache.count(key)){
// 如果 key 不存在,创建一个新的节点
Node* node = new Node(key,value);
// 添加进哈希表
cache[key]=node;
size++;
// 添加至双向链表的头部
add_to_head(node);
if(size>capacity){
// 如果超出容量,删除双向链表的尾部节点
Node* drop_node = remove_tail();
// 删除哈希表中对应的项
cache.erase(drop_node->key);
// 防止内存泄漏
delete drop_node;
size--;
}
}
//如果当前缓存中有
else{
// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
Node* node = cache[key];
node->value = value;
move_to_head(node);
}
}
void add_to_head(Node* node){
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
}
void remove_node(Node* node){
node->prev->next = node->next;
node->next->prev = node->prev;
}
void move_to_head(Node* node){
remove_node(node);
add_to_head(node);
}
Node* remove_tail(){
Node* node = tail->prev;
remove_node(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);
*/