当前位置:网站首页>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缓存
边栏推荐
- Data Lake (19): SQL API reads Kafka data and writes it to Iceberg table in real time
- 关于我放弃考研这件事儿
- 0x80070570文件或目录损坏且无法删除(0x80070091怎么删除)
- TOGAF10标准读书会第2场活动精彩继续,高光时刻回顾!
- Fully Dynamically Constrained Robot Efficient Time-Optimal Trajectory Planning
- 这款悄然崛起的国产API接口管理工具,你一定要晓得
- 立一个flag
- JVS函数公式使用场景介绍
- FIFO深度计算学习记录(汇总)
- Exploring Plain Vision Transformer Backbones for Object Detection 论文阅读笔记
猜你喜欢

Docker build Mysql master-slave replication

ESP8266-Arduino编程实例-HDC1008温度湿度传感器驱动

MySql模糊查询大全

Is the working process of the belt you know the story - actionreducerstore

JVS应用中心

The item 'node.exe' was not recognized as the name of a cmdlet, function, script file, or runnable program.

Redis学习笔记-3.慢查询和其他高级数据结构

WebGL给Unity传递参数问题1: Cannot read properties of undefined (reading ‘SendMessage‘)

多线程学习笔记-2.final关键字和不变性

通过斐波那契数再谈函数递归2.0
随机推荐
最长算术(暑假每日一题 11)
The most complete phpmyadmin vulnerability summary
Qt鼠标穿透
带有对称约束切换线性系统的结构可控性
lotus-local-net 2k v1.17.0-rc4
Three-Phase PWM Rectifier Predictive Direct Power Control
科学论文和学术论文写作
TOGAF10标准读书会第2场活动精彩继续,高光时刻回顾!
am335x 看门狗驱动&看门狗应用例程序
[Shader] Shader official example [easy to understand]
ipv4和ipv6对比(IPV4)
基于稳态视觉诱发电位和注意力脑电的混合脑机接口系统
Hybrid brain-computer interface system based on steady-state visual evoked potentials and attentional EEG
Acwing第 62 场周赛【未完结】
第十二章 使用中的 OpenAPI 属性
关于我放弃考研这件事儿
基于生物激励神经网络的室内实时激光SLAM控制方法
栈和队列的基本概念
SAP ABAP OData 服务如何支持 $filter (过滤)操作试读版
学习笔记 Golang 写入文件(io.WriteString、ioutil.WriteFile、file.Write、write.WriteString)