LRU缓存算法设计

LRU 缓存算法的核⼼数据结构就是哈希链表双向链表哈希表 的结合体。这个数据结构⻓这样:

创建的需要有两个方法,一个是get方法,一个是put方法。

一些问题:为什么需要使用双向链表呢?因为删除链表的本身,需要得到他的前一个节点。如果使用单链表,效率就会很低,这边是使用的空间换取效率。

java 复制代码
//Node 节点类
public class Node {
    public  int key,val;
    public Node pre,next;
    public Node(int key,int val){
        this.key=key;
        this.val=val;
    }

}
java 复制代码
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; }
}

缓存设计的代码:

java 复制代码
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已经被移除去了。

相关推荐
特立独行的猫a6 分钟前
11款常用C++在线编译与运行平台推荐与对比
java·开发语言·c++
louisgeek16 分钟前
Java 位运算
java
绝无仅有44 分钟前
企微审批对接错误与解决方案
后端·算法·架构
hweiyu001 小时前
Maven 私库
java·maven
Super Rookie1 小时前
Spring Boot 企业项目技术选型
java·spring boot·后端
写不出来就跑路1 小时前
Spring Security架构与实战全解析
java·spring·架构
用户5040827858392 小时前
1. RAG 权威指南:从本地实现到生产级优化的全面实践
算法
ZeroNews内网穿透2 小时前
服装零售企业跨区域运营难题破解方案
java·大数据·运维·服务器·数据库·tcp/ip·零售
sleepcattt2 小时前
Spring中Bean的实例化(xml)
xml·java·spring