算法通关村第5关【黄金】| LRU设计与实现

什么是LRU?

LRU(最近最少使用)是一种缓存淘汰策略,用于在缓存容量有限时,选择最近最少使用的缓存项进行淘汰,以便为新的数据留出空间。LRU 算法的基本思想是,当缓存已满并且需要插入新数据时,会将最久未被访问的数据从缓存中删除。

怎么实现?

LRU 算法的实现方式可以是通过维护一个双向链表和一个哈希表来实现。双向链表用来记录缓存中数据项的访问顺序,最近被访问的数据项放在链表的头部,最久未被访问的数据项放在链表的尾部。哈希表用来存储每个数据项的地址,以便在 O(1) 时间内查找链表中的对应节点。

当有新数据访问时,LRU 算法会执行以下操作:

  1. 如果数据在缓存中,将数据移到链表头部(表示最近访问过)。
  2. 如果数据不在缓存中,检查缓存是否已满。若已满,则删除链表尾部的数据项,再将新数据插入链表头部。
  3. 如果数据不在缓存中,且缓存未满,将新数据插入链表头部。

LRU 算法的优点是可以有效地利用缓存空间,保持缓存中数据的热度。然而,实际实现中需要考虑查找、插入、删除操作的效率,以及处理哈希冲突等问题。

代码

  • 虚拟头尾结点互指
  • 只有完全新增size才++
  • 自建双向链表结构
  • 哈希表存key和node
public class LRUCache {
    class DLinkedList{
        DLinkedList pre;
        DLinkedList next;
        Integer value;
        Integer key;
        public DLinkedList(){}
        public DLinkedList(int key,int value){
        this.key = key;
        this.value = value;
        }
    }
    
    int size;
    int capacity;
    DLinkedList head;
    DLinkedList tail;
    Map hashTable;

    public LRUCache(int capacity) {
        head = new DLinkedList(-1,-1);
        tail = new DLinkedList(-1,-1);
        hashTable = new HashMap<>();
        head.next = tail;
        tail.pre = head;
        size = 0;
        this.capacity = capacity;

    }
    
    public int get(int key) {
        DLinkedList res = hashTable.get(key);
        if(res != null){
            moveTohead(res);
            return res.value;
        }
        return -1;
    }
    
    public void put(int key, int value) {
        DLinkedList res = hashTable.get(key);
        if(res == null){
            DLinkedList node = new DLinkedList(key,value);
            hashTable.put(key,node);
            if(size

你可能感兴趣的:(算法,数据结构,算法)