当前位置:网站首页>LRU缓存[线性表 -> 链表 -> hash定位 -> 双向链表]
LRU缓存[线性表 -> 链表 -> hash定位 -> 双向链表]
2022-07-31 12:17:00 【REN_林森】
前言
对于LRU缓存,记忆根在hash + 双向链表,而分析的逻辑为线性表 -> 链表 -> hash定位 -> 双向链表。
一、LRU缓存

二、从线性表到hash + 双向链表
package everyday.medium;
import java.util.HashMap;
import java.util.Map;
// LRU缓存
public class LRUCache {
/* 存在固定容量的Entry线性表,put/get时 -> 当容量足时,则寻找Entry将其删除,再在线性表后加入Entry。 当容量不足时,寻找Entry将其删掉,如果没有应该删第一个Entry,由此可见线性表物理结构应该采用链表。 注意到要寻找Entry,可采用hash来快速定位Entry。 注意到要删除hash定位到的节点,而不是遍历的方式,这需要双向链表来获取前驱后继。 review: idea:从线性表 -> 链表 -> hash -> 双向链表 core:链表操作,防止断链,核心:不要把当前节点的prev/next先断掉就行,比较需要靠它把前驱后继联系起来。 辅助:hash提速。 回忆逻辑根:双向链表 + hash定位。 */
int capacity;
Node dummyHead, dummyTail;
Map<Integer, Node> fx;
int len;
public LRUCache(int capacity) {
this.capacity = capacity;
dummyHead = new Node(-1, -1);
dummyTail = new Node(-1, -1);
dummyHead.next = dummyTail;
dummyTail.prev = dummyHead;
fx = new HashMap<>();
}
public int get(int key) {
Node n = fx.get(key);
if (n == null) return -1;
// step1:访问过,应该将节点移到末尾。
n.prev.next = n.next;
n.next.prev = n.prev;
// 很明显,这个可以复用,整成函数。
dummyTail.prev.next = n;
n.prev = dummyTail.prev;
dummyTail.prev = n;
n.next = dummyTail;
return n.value;
}
public void put(int key, int value) {
if (fx.containsKey(key)) {
// 移除指定节点即可。
Node n = fx.get(key);
n.prev.next = n.next;
n.next.prev = n.prev;
--len;
}
if (len >= capacity) {
// step1:链表移除头节点;
Node old = dummyHead.next;
dummyHead.next = dummyHead.next.next;
dummyHead.next.prev = dummyHead;
// step2:map移除旧节点。
fx.remove(old.key);
--len;
}
Node n = new Node(key, value);
// step1:插入新节点到链表最后。
dummyTail.prev.next = n;
n.prev = dummyTail.prev;
n.next = dummyTail;
dummyTail.prev = n;
// step2:插入新节点到map
fx.put(key, n);
++len;
}
static class Node {
int key, value;
Node prev, next;
Node(int k, int v) {
key = k;
value = v;
}
}
}
总结
1)总结一个知识点的逻辑根,辅助自己将来碰到同样的题进行快速分析。如LRU回忆逻辑根hash+双向链表,再写时可从线性表分析到双向链表。
2)线性表 -> 链表 -> hash定位 -> 双向链表,缺什么数据结构拿什么数据结构,无法将idea转码,就面向循环分支进行抽象,以达到问题转换。
参考文献
[1] LeetCode LRU缓存
边栏推荐
猜你喜欢
随机推荐
榕树贷款GPU 硬件架构
Double non-one into bytes!!Pure dry goods sharing
R语言:文本(字符串)处理与正则表达式
通过斐波那契数再谈函数递归2.0
Qt鼠标穿透
亲测可用!!!WPF中遍历整个窗口的所有TextBox组件,对每个输入框做非空判断。
Read through the interface to call the artifact RestTemplate
vivado里那些看不懂的原语
Use IN List Population in Your JDBC Application to Avoid Cursor Cache Contention Issues
如何正确地把服务器端返回的文件二进制流写入到本地保存成文件
How does the SAP ABAP OData service support the $filter (filter) operation trial version
SAP ABAP OData 服务如何支持 $filter (过滤)操作试读版
学习爬虫之Scrapy框架学习(1)---Scrapy框架初学习及豆瓣top250电影信息获取的实战!
dosbox基础使用[通俗易懂]
学习笔记 Golang 写入文件(io.WriteString、ioutil.WriteFile、file.Write、write.WriteString)
深圳某游戏研发公司每个工位都装监控,网友:堪比“坐牢”!
[Shader] Shader official example [easy to understand]
三相PWM整流器预测直接功率控制
使用docker搭建mysql主从
安装MYSQL遇到问题:write configuration file卡主








