LRU 缓存算法思想及代码解析
算法思想
LRU(Least Recently Used,最近最少使用)缓存 需要满足以下要求:
- 在 O(1) 时间复杂度内完成
get
和put
操作。 - 当缓存满时,删除最近最少使用的元素(即最久没有被访问的元素)。
- 每次访问或插入数据,都需要将该数据提升为最近使用的状态。
为了实现这一目标,我们使用 哈希表(HashMap)+ 双向链表(Doubly Linked List) 的数据结构组合:
- 哈希表(
Map<Integer, Node>
)用于 O(1) 时间查找键值对。 - 双向链表 维护数据访问的顺序:
- 最近使用的数据位于链表头部(head.next)。
- 最久未使用的数据位于链表尾部(tail.prev)。
- 插入、删除节点均为 O(1) 操作。
代码解析
1. 设计数据结构
class Node {
int key, value;
Node prev, next;
Node(int key, int value) {
this.key = key;
this.value = value;
}
}
- Node 结构用于双向链表,每个节点存储
key-value
键值对,并且有prev
和next
指针,用于快速在链表中移动。
2. LRUCache 构造方法
private final int capacity;
private final Map<Integer, Node> cache;
private final Node head, tail;
public LRUCache(int capacity) {
this.capacity = capacity;
this.cache = new HashMap<>();
this.head = new Node(0, 0); // 虚拟头节点
this.tail = new Node(0, 0); // 虚拟尾节点
head.next = tail;
tail.prev = head;
}
capacity
:缓存的最大容量。cache
:哈希表,存储key -> Node
,用于 O(1) 查找。head, tail
:虚拟头尾节点,方便插入和删除操作。
3. get(int key)
方法
public int get(int key) {
if (!cache.containsKey(key)) {
return -1;
}
Node node = cache.get(key);
moveToHead