• 每天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;
        }
       
    }
  • 相关阅读:
    ant build打包
    在JAVA中如何获取当前源文件名以及代码的行号
    react以组件为中心的代码分割和懒加载
    java中针对 try和finally一些总结
    JS强制关闭浏览器页签并且不提示关闭信息
    由[].slice.call()引发的思考
    JS类型判断
    nginx的location配置
    DBCP连接池
    java/Servlet
  • 原文地址:https://www.cnblogs.com/s648667069/p/13899067.html
Copyright © 2020-2023  润新知