LRU缓存算法设计详解
创作时间:
作者:
@小白创作中心
LRU缓存算法设计详解
引用
CSDN
1.
https://blog.csdn.net/ngczx/article/details/140229679
LRU(Least Recently Used)缓存算法是一种常用的缓存淘汰策略,其核心思想是“最近最少使用”。在计算机系统中,缓存的容量是有限的,当缓存满时,需要根据一定的策略淘汰一些数据,以腾出空间存放新的数据。LRU算法就是一种基于访问频率的淘汰策略,它会优先淘汰那些长时间没有被访问的数据。本文将详细介绍LRU缓存算法的设计原理和实现方法。
LRU 缓存算法的核⼼数据结构就是哈希链表,双向链表和哈希表的结合体。这个数据结构⻓这样:
创建的需要有两个方法,一个是get方法,一个是put方法。
一些问题:为什么需要使用双向链表呢?因为删除链表的本身,需要得到他的前一个节点。如果使用单链表,效率就会很低,这边是使用的空间换取效率。
//Node 节点类
public class Node {
public int key,val;
public Node pre,next;
public Node(int key,int val){
this.key=key;
this.val=val;
}
}
public class DoubleList {
//头和尾
public Node head,tail;
public int size;
public DoubleList(){
//两个哨兵
head=new Node(0,0);
tail=new Node(0,0);
head.next=tail;
tail.pre=head;
size=0;
}
public void addLast(Node x){
//添加到末尾去
//在tail之前插入一个
x.pre=tail.pre; //
x.next=tail;
tail.pre.next=x;
tail.pre=x;
size++;
}
public void remove(Node x) {
//双链表删除一个节点 x.pre.next=x.next;
x.pre.next = x.next;
x.next.pre = x.pre;
size--;
}
// 删除链表中第⼀个节点,并返回该节点,时间 O(1)
public Node removeFirst() {
if (head.next == tail)
return null;
Node first = head.next;
remove(first);
return first;
}
public int size() { return size; }
}
缓存设计的代码:
import java.util.HashMap;
public class LRUCache {
// key -> Node(key, val)
private HashMap<Integer, Node> map;
// Node(k1, v1) <-> Node(k2, v2)...
private DoubleList cache;
// 最⼤容量
private int cap; //最大容量
public LRUCache(int capacity) {
this.cap = capacity;
map = new HashMap<>();
cache = new DoubleList();
}
private void makeRecently(int key) {
Node x = map.get(key); //变为最近的 删除 然后添加进来
// 先从链表中删除这个节点
cache.remove(x);
// 重新插到队尾
cache.addLast(x);
}
private void addRecently(int key, int val) {
Node x = new Node(key, val);
// 链表尾部就是最近使⽤的元素
cache.addLast(x);
// 别忘了在 map 中添加 key 的映射
map.put(key, x);
}
private void deleteKey(int key) {
Node x = map.get(key);
// 从链表中删除
cache.remove(x);
// 从 map 中删除
map.remove(key); //mp中也要删除
}
private void removeLeastRecently() { //删除最久没有使用的
// 链表头部的第⼀个元素就是最久未使⽤的
Node deletedNode = cache.removeFirst();
// 同时别忘了从 map 中删除它的 key
int deletedKey = deletedNode.key;
map.remove(deletedKey);
}
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
// 将该数据提升为最近使⽤的
makeRecently(key); //修改
return map.get(key).val;
}
public void put(int key, int val) {
//如果之前含有 删除 并添加
if (map.containsKey(key)) {
// 删除旧的数据
deleteKey(key);
// 新插⼊的数据为最近使⽤的数据
addRecently(key, val);
return;
}
//如果慢了 那么删除
if (cap == cache.size()) {
// 删除最久未使⽤的元素
removeLeastRecently();
}
// 添加为最近使⽤的元素
addRecently(key, val);
}
}
一些算法的设计思路:,变为最近的。首先得到这个点,然后删除这个点。
添加到最近来 就需要new出来这个节点,然后加入到最后去。
删除 首先先得到,再从链表中删除掉。不要忘记hashmap中也是需要删除的。
如果满了,需要删除掉最早的那个节点。
test测试结果
通过测试发现 2已经被移除去了。
热门推荐
公司分红需要缴纳哪些税
租庸调制的影响与历史意义
浅蓝色用英语如何表示
吃青枣有什么好处?懂得食用可获得6个好处,但3个禁忌也别忽视
上海电机学院怎么样 好不好
高温来袭供电紧张,日本政府呼吁东京市民下午关灯三小时
如何在WPS云文档网页端生成并分享文件链接
为什么说一张纸对折105次宇宙都装不下,这到底是真的吗
退休医保:门诊住院待遇全解析
亲临电影美景:挂在瀑布上的千年古镇——芙蓉镇景点介绍
种植牙真的会显得丑吗?探讨种植牙的美观性与适应性
溶解度单位大盘点:从基础概念到实际应用
探究化妆品消费者市场需求:满足消费者需求的新趋势
从网瘾少年到企业高管:钟生明的逆袭之路
春天最美是什么?春天最美:万物复苏的生机与希望!
不可忽视的“颈部隐患”:颈动脉斑块!斑块如何形成?如何检测?
紫叶酢浆草的养殖方法和注意事项
学会简单炒菜的规则,掌握基本的烹饪技巧和方法
葡萄糖6磷酸脱氢酶新生儿筛查与诊断的方法
四驱工作原理图解!什么是全时四驱?什么是分时四驱?
孕妇可以用的防晒霜有哪些
研究显示:面包、燕麦、酸奶...长期吃这类食物让人变胖还变傻!
买第二套房子税收怎么收费?安置房买卖指南
科技将把人类带向何处?
强电与弱电,家居中的电力双雄——深入解析与实际应用
Excel曲线图美化指南:从颜色到布局的全方位优化技巧
时隔5年归来仍是王者!张国伟复出之战2米24夺冠 王宇2米15第五
车祸突发别慌!这份指南带你冷静应对事故发生
血栓闭塞性脉管炎(柏格氏病):症状、病因及预防
6大数学分支,织就一张纠缠的思想网,成为人类最强大的创造