LRU算法(面试遇到两次)

原理: 

最近最久未使用(Least Recently Used    LRU)算法是⼀种缓存淘汰策略。如果新存入或者访问一个值,则将这个值放在队列开头。如果存储容量超过上限cap,那么删除队尾元素,再存入新的值。新插入的元素或者最新查询的元素要放到链表的头部,对于长时间未访问的元素要放到链表尾部,所以每次插入或者查询都需要维护链表中元素的顺序。

代码:

public class LRUCache {
    class DLinkedNode {
        int key;
        int value;
        DLinkedNode prev;
        DLinkedNode next;
        public DLinkedNode() {}
        public DLinkedNode(int _key, int _value) {key = _key; value = _value;}
    }
 
    private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();
    private int size;
    private int capacity;
    private DLinkedNode head, tail;
 
    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        // 使用伪头部和伪尾部节点
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.prev = head;
    }
 
    public int get(int key) {
        DLinkedNode node = cache.get(key);
        if (node == null) {
            return -1;
        }
        // 如果 key 存在,先通过哈希表定位,再移到头部
        moveToHead(node);
        return node.value;
    }
 
    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);
        if (node == null) {
            // 如果 key 不存在,创建一个新的节点
            DLinkedNode newNode = new DLinkedNode(key, value);
            // 添加进哈希表
            cache.put(key, newNode);
            // 添加至双向链表的头部
            addToHead(newNode);
            ++size;
            if (size > capacity) {
                // 如果超出容量,删除双向链表的尾部节点
                DLinkedNode tail = removeTail();
                // 删除哈希表中对应的项
                cache.remove(tail.key);
                --size;
            }
        }
        else {
            // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
            node.value = value;
            moveToHead(node);
        }
    }
 
    private void addToHead(DLinkedNode node) {
        node.prev = head;
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
    }
 
    private void removeNode(DLinkedNode node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
 
    private void moveToHead(DLinkedNode node) {
        removeNode(node);
        addToHead(node);
    }
 
    private DLinkedNode removeTail() {
        DLinkedNode res = tail.prev;
        removeNode(res);
        return res;
    }
}

相关推荐

  1. LRU算法面试遇到

    2023-12-20 08:14:05       74 阅读
  2. 面试算法-102-LRU 缓存

    2023-12-20 08:14:05       39 阅读
  3. 面试算法-168-LRU 缓存

    2023-12-20 08:14:05       32 阅读
  4. <span style='color:red;'>LRU</span><span style='color:red;'>算法</span>

    LRU算法

    2023-12-20 08:14:05      59 阅读
  5. 缓存淘汰(LRU算法

    2023-12-20 08:14:05       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-20 08:14:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-20 08:14:05       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-20 08:14:05       87 阅读
  4. Python语言-面向对象

    2023-12-20 08:14:05       96 阅读

热门阅读

  1. UE5 C++中 Actor内填加编辑器内模型

    2023-12-20 08:14:05       60 阅读
  2. H3C 交换机指示灯说明

    2023-12-20 08:14:05       260 阅读
  3. Axure

    Axure

    2023-12-20 08:14:05      65 阅读
  4. redis——分布式锁

    2023-12-20 08:14:05       60 阅读
  5. CSS基础

    2023-12-20 08:14:05       52 阅读
  6. BKP外设

    BKP外设

    2023-12-20 08:14:05      53 阅读
  7. 【.NET Core】反射(Reflection)详解(一)

    2023-12-20 08:14:05       53 阅读
  8. AWS S3相关配置笔记

    2023-12-20 08:14:05       66 阅读
  9. 【优化】Springboot 修改 tomcat连接池

    2023-12-20 08:14:05       62 阅读