每天1题算法题(11)- LRU缓存机制

运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

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

示例:

 

方法一:哈希表 + 双向链表

双向链表按照被使用的顺序存储了这些键值对,靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久未使用的。

哈希表即为普通的哈希映射(HashMap),通过缓存数据的键映射到其在双向链表中的位置。

class LRUCache {

    private int capacity;
    private int size;

    private Map<Integer, DLinkedNode> cache = new HashMap();

    private DLinkedNode head,tail;

    class DLinkedNode {
        int key;
        int value;
        DLinkedNode prev;
        DLinkedNode next;
        public DLinkedNode() {}
        public DLinkedNode(int _key, int _value) {key = _key; value = _value;}
    }


    public LRUCache(int capacity) {
        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;
         } else {
             moveToHead(node);
             return node.value;
         }
    }
    
    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);
        if(node == null) {
            DLinkedNode newNode = new DLinkedNode(key, value);
            cache.put(key, newNode);
            addToHead(newNode);
            size++;
            if(size > capacity) {
                DLinkedNode tailNode = removeTail();
                cache.remove(tailNode.key);
                size --;
            }
        } else {
            node.value = value;
            moveToHead(node);
        }
    }

    private void addToHead(DLinkedNode node) {
        DLinkedNode preSecondNode = head.next;
        head.next = node;
        node.prev = head;
        preSecondNode.prev = node;
        node.next = preSecondNode;
    }

    private void moveToHead(DLinkedNode node) {
        DLinkedNode appendPrevNode = node.prev;
        DLinkedNode appendNextNode = node.next;
        appendPrevNode.next = appendNextNode;
        appendNextNode.prev = appendPrevNode;
        DLinkedNode preSecondNode = head.next;
        head.next = node;
        node.prev = head;
        node.next = preSecondNode;
        preSecondNode.prev = node;

    }

    private DLinkedNode removeTail() {
        DLinkedNode tailNode = tail.prev;
        DLinkedNode pretailNode = tailNode.prev;
        tail.prev = pretailNode;
        pretailNode.next = tail;
        return tailNode;
    }
   
}

 

posted @ 2020-10-29 20:34  GodTelMe  阅读(117)  评论(0编辑  收藏  举报