zoukankan      html  css  js  c++  java
  • LRU缓存实现(手写版)

    运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
     
    获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
    写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
     
     
     
    进阶:
     
    你是否可以在 O(1) 时间复杂度内完成这两种操作?
     
     
     
    示例:
     
    LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
     
    cache.put(1, 1);
    cache.put(2, 2);
    cache.get(1); // 返回 1
    cache.put(3, 3); // 该操作会使得关键字 2 作废
    cache.get(2); // 返回 -1 (未找到)
    cache.put(4, 4); // 该操作会使得关键字 1 作废
    cache.get(1); // 返回 -1 (未找到)
    cache.get(3); // 返回 3
    cache.get(4); // 返回 4
     
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/lru-cache
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
     
    实现思路:查找和插入的时间复杂度都需要是O(1),那么只能通过hash表+双向链表的方式实现(LinkedHashMap就是这种方式),这里首先使用自定义的一个双向链表进行实现。
     
     
        private int headKey;
     
        private int lastKey;
     
        private Map<Integer,Node> map;
     
        private int capacity;
     
        public LRUCache(int capacity) {
            headKey = -1;
            lastKey = -1;
            this.capacity = capacity;
            map = new HashMap<>(capacity);
        }
     
        /**
         * 将节点移动到尾节点
         * @param n
         */
        private void changeNodeToLast(Node n){
            //判断是否有头节点
            if(headKey == -1){
                headKey = n.key;
            }
            //判断当前节点是否是尾节点
            if(lastKey == n.key){
                return;
            }
            //判断当前节点是否是头节点
            if(headKey == n.key){
                //判断当前是否只有一个节点
                if(n.after == null){
                    return;
                }
                headKey = n.after.key;
            }
            Node b = n.before;
            Node a = n.after;
            //将当前节点移动到尾节点
            if(b != null){
                b.after = a;
            }
            if(a != null){
                a.before = b;
            }
            Node last = map.get(lastKey);
            lastKey = n.key;
            n.before = last;
            last.after = n;
            last = n;
            last.after = null;
        }
     
        /**
         * 添加新节点
         * @param key
         * @return
         */
        private Node addNewNode(int key){
            Node n = new Node();
            //是否有头节点
            if(headKey == -1){
                headKey = key;
            }
            //是否有尾节点
            else if(lastKey == -1){
                lastKey = key;
                Node head = map.get(headKey);
                n.before = head;
                head.after = n;
            }else{
                //中间节点处理
                Node last = map.get(lastKey);
                n.before = last;
                last.after = n;
                lastKey = key;
            }
            return n;
        }
     
        /**
         * 移除头节点
         */
        private void removeNode(){
            Node node = map.get(headKey);
            map.remove(headKey);
            if(node.after != null){
                headKey = node.after.key;
                node.after.before = null;
            }else{
                headKey = -1;
                lastKey = -1;
            }
        }
        
        public int get(int key) {
            Node n = map.get(key);
            if(n != null){
                this.changeNodeToLast(n);
                return n.value;
            }
            return -1;
        }
        
        public void put(int key, int value) {
            Node n = map.get(key);
            if(n == null){
                if(map.size()>= capacity){
                   this.removeNode();
                }
                n = this.addNewNode(key);
                n.key = key;
                n.value = value;
                map.put(key,n); 
            }else{ 
               this.changeNodeToLast(n);
               n.key = key;
               n.value = value;
            }
        }
     
        private class Node{
            public Node before;
     
            public int key ;
     
            private int value;
     
            private Node after;
     
            public Node(){
                key = -1;
                value = -1;
            }
     
        }
    力扣执行结果:

     下一章通过继承LinkedHashMap进行实现。https://www.cnblogs.com/ymqj520/p/13634002.html

  • 相关阅读:
    洛谷P1306 斐波那契公约数
    Codevs 1688 求逆序对(权值线段树)
    poj1006 Biorhythms
    2017-9-2 NOIP模拟赛
    洛谷P1633 二进制
    洛谷P2513 [HAOI2009]逆序对数列
    洛谷P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower
    洛谷P2285 [HNOI2004]打鼹鼠
    2017-8-31 NOIP模拟赛
    洛谷P2134 百日旅行
  • 原文地址:https://www.cnblogs.com/ymqj520/p/13633159.html
Copyright © 2011-2022 走看看