LRU最近最少使用的缓存

LRU

  • 题目描述
  • 题解方法
  • 学习链接

题目描述

LRU:最近最少使用缓存
数据结构,设计和实现一个 LRU (Least Recently Used,最近最少使用) 缓存机制 。实现 LRUCache 类:
LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
https://leetcode.cn/problems/OrIXps/

题解方法

LRU 缓存机制可以通过哈希表辅以双向链表实现,我们用一个哈希表和一个双向链表维护所有在缓存中的键值对。
双向链表按照被使用的顺序存储了这些键值对,靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久未使用的。
哈希表即为普通的哈希映射(HashMap),通过缓存数据的键映射到其在双向链表中的位置。
题目思考:ArrayList和LinkedList相比插入和删除很慢,所以选用链表LinkedList,方法一使用java语言自己封装好的数据结构LinkedHashMap

class LRUCache extends LinkedHashMap<Integer,Integer>{
    private int capacity;
    public LRUCache(int capacity) {
        super(capacity,0.75F,true);
        this.capacity = capacity;
    }
    
    public int get(int key) {
        return super.getOrDefault(key,-1);
    }
    
    public void put(int key, int value) {
        super.put(key,value);
    }
    
    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer,Integer> eldest){
        return size() > capacity;
    }
}

关键方法removeEldestEntry实现最近最少使用的缓存删除

方法二:自己实现一个双向链表和hash表
实现思路,在LRU缓存类中维护一个Node的内部类,和一个缓存Map,实现每一个value就是一个Entry,entry之间是双向链表的关系,在链表之间加入head,和tail的entry节点,所有的数据节点都是在这两个之间进行的插入和查询。设置size表示当前缓存的数量大小,capacity表述缓存的容量,一旦size > capacity就需要执行LRU算法,实现最近最少使用数据的删除和新热点数据的头插入。
最近最少使用的关键就是,get数据和insert数据的判断;
get(int key)通过传入的指定的一个key,获取到对应的节点Entry,如何获取到的节点为null的话就是没有此节点,返回-1即可。否则就需要移动此节点到头部位置,变为热点数据,同时返回节点的value值
put(int key, int value)的方法就比较麻烦了,通过key获取到节点node,此节点不为空,就说明缓存中具有此节点,更新此节点的value,将此节点移动到头部,返回即可。
若此节点为空就说明要添加这个节点了,这时候就要判断缓存数量是否达到缓存容量,如果等于缓存容量就需要尾节点删除,缓存删除,缓存数目减少;如果没有达到缓存容量的话,就直接将节点信息封装成一个节点,添加到头结点即可,缓存添加,缓存数目增加。
moveToHead(Entry node)函数实现移动缓存中的节点,先删除缓存中的节点【关系】,将这个节点放到头结点上。
initLinkedList()就是将head和tail链表双向维护起来,等待插入节点。

class LRUCache{
    private Entry head,tail;
    private Map<Integer,Entry> cache;
    // 当前缓存存入数据的个数
    private int size;
    // 设置缓存的容量
    private int capacity;

    public static class Entry{
        private Entry pre;
        private Entry next;
        private int key;
        private int value;
        
        public Entry(){}
        public Entry(int key,int value){
            this.key = key;
            this.value = value;
        }
    }
    
    // LRU缓存容量的设置
    public LRUCache(int capacity) {
        this.capacity = capacity;
        initLinkedList();
        size = 0;
        cache = new HashMap<>(capacity+2);
    }
    
    
    public int get(int key) {
        Entry node = cache.get(key);
        if(node == null){
            return -1;
        }
        moveToHead(node);
        return node.value;
    }
    
    public void put(int key, int value) {
        Entry node = cache.get(key);
        // 存在这个节点,当前节点变为热点节点,移动到链表的头部
        if(node != null){
            node.value = value;
            moveToHead(node);
            return;
        }
        // 不存在这个节点,就要加入到链表头部
        if(size == capacity){
            Entry lastNode = tail.pre;
            deleteNode(lastNode);
            cache.remove(lastNode.key);
            size--;
        }
        // 新数据加入
        Entry newNode = new Entry();
        newNode.key = key;
        newNode.value = value;
        addNode(newNode);
        cache.put(key,newNode);
        size++;
    }
    
    private void moveToHead(Entry node){
        deleteNode(node);
        addNode(node);
    }
    private void deleteNode(Entry node){
        node.pre.next=node.next;
        node.next.pre=node.pre;
    }
    private void addNode(Entry node){
        head.next.pre = node;
        node.next = head.next;
        head.next = node;
        node.pre = head;
    }
    
    private void initLinkedList(){
        head = new Entry();
        tail = new Entry();
        
        head.next = tail;
        tail.pre = head;
    }
    
}

学习链接

https://leetcode.cn/problems/OrIXps/solution/zui-jin-zui-shao-shi-yong-huan-cun-by-le-p3c2/

https://www.bilibili.com/video/BV1Va411677h/spm_id_from=333.999.0.0&vd_source=19dff15423f85b7846e6fb83dd734fc4

你可能感兴趣的:(LeetCode,缓存,链表,数据结构)