算法模拟题——设计LRU缓存结构

该文详细介绍了如何设计一个LRU缓存结构,利用淘汰算法在缓存满时删除最久未使用的key-value对。通过定义Node节点组成双向链表,并结合HashMap存储key-value,每次操作时将数据移到链表头部。当达到容量上限时,会从链表尾部删除节点。set和get方法分别用于插入/更新数据和获取数据,同时更新链表状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计LRU缓存结构

核心思想

当缓存满时执行淘汰算法, 删除缓存中最久未使用的key-value

解决思路

定义一个Node节点,包含前向和后向指针,使用map存储key-node,同时每次操作数据,插入新数据和更新数据,都将数据放置双向链表的头部,保证链表尾部的节点为最久未使用的数据,缓存满时就从表位删除节点。

具体代码

1 定义Node
class Node {
        int key;
        int val;
        //前向指针
        Node pre;
        //后继指针
        Node next;
        public Node(int key, int val,Node prev, Node next) {
            this.key = key;
            this.val = val;
            this.pre = pre;
            this.next = next;
        }
    }
2 初始化
	//哈希表
    private Map<Integer,Node> map = new HashMap<>();
    //设置一个头节点
    private Node  head;
    //设置一个尾节点
    private Node tail;
    //设置容量
    private int capacity;
    //记录已使用的容量
    private int used;
3 set(int key, int val)
public void set(int key, int value) {
        //如果 key 已存在,直接修改值,并移动到链表头部
        if(map.containsKey(key)){
            map.get(key).val = value;
            //更新节点的状态。将节点移动到头部
            makeRecently(key);
            return;
        }
        //如果达到容量上限,就移除尾部节点,注意HashMap要remove
        if(used == capacity){
        	//删除尾部节点
            map.remove(tail.key);
            //尾节点更新
            tail = tail.pre;
            tail.next = null;
            //已使用容量减一
            used--;
        }
        //头结点为空,单独处理
        if(head == null){
            head = new Node(key, value, null,null);
            tail = head;
        }else{
        	//头节点不为空,将节点插入头部
            Node t = new Node(key, value, null, head);
            head.pre = t;
            head = t;
        }
        //所以map 存的永远是头节点
        map.put(key, head);
        used++;

    }
4 get(int key)
 public int get(int key) {
        // 判断是有
        if(!map.containsKey(key)){
        	//没有值返回-1
            return -1;
        }
        //有就返回值,但是get操作也需要更新节点状态
        makeRecently(key);
        return map.get(key).val;
    }
5 重头戏,更新节点状态的函数 makeRecantly(int key),可以看图理解
 private void makeRecently(int key){
 		//获取节点,将节点移动到头部
        Node t = map.get(key);
        //更新的节点不是头节点
        if(t != head){
        	//如果是尾节点,更新尾部节点
            if(t == tail){
                tail = tail.pre;
                tail.next = null;
            }
            else{
            //不是尾部节点,更新前后指针,具体看图理解
                t.pre.next = t.next;
                t.next.pre = t.pre;
            }
            //因为t移动到了头部,所以前指针为空,后指针为旧的头节点
            t.pre = null;
            t.next = head;
            head.pre = t;
            head = t;
        }
    }

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YuannaY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值