LRU缓存机制

164 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制 。 实现 LRUCache 类:

LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。 void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

来源:力扣(LeetCode)

难度:medium

思路

1.一个双向链表节点存储key和value

2.一个map集合存储key和双向链表节点的映射

3.一个辅助头节点一个辅助尾节点,更新或者添加时将节点加到辅助头节点后面,删除时删除辅助尾节点后面的元素

代码

class LRUCache {
    int capacity; //缓存的最大容量
    int size; //当前使用的容量
    //创建一个辅助头节点
    DListNode head;
    //创建一个辅助尾节点
    DListNode tail;
    Map<Integer, DListNode> map; //记录key和对应的双向链表节点的映射

    class DListNode {
        DListNode pre;
        DListNode next;
        int key;
        int value;
        public DListNode(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.head = new DListNode(-1, -1);
        this.tail = new DListNode(-1, -1);
        head.next = tail;
        tail.pre = head;
        map = new HashMap<>();
    }

    public int get(int key) {
        if (map.get(key) == null) return -1;
        addToHead(map.get(key));
        return map.get(key).value;
    }

    public void put(int key, int value) {
        if (map.get(key) != null) {
            map.get(key).value = value; //更新值
            addToHead(map.get(key));
            return;
        }
        DListNode node = new DListNode(key, value);
        addToHead(node);
        map.put(key, node);
        size++;
        if (size > capacity) {
            removeTail();
        }
    }

    public void addToHead(DListNode node) {
        if (node.pre != null && node.next != null) { //判断这个是新节点加入还是老节点更新
            node.next.pre = node.pre;
            node.pre.next = node.next;
        }
        node.pre = head;
        node.next = head.next;
        head.next.pre = node;
        head.next = node;
    }

    public void removeTail() {  //删除尾节点
        map.remove(tail.pre.key);
        tail.pre.pre.next = tail;
        tail.pre = tail.pre.pre;
        size--;  //删除之后使用的容量变少了

    }
}