Design LRU Least Recently Used 设计最近最少使用算法

LRU Least Recently Used 最近最少使用算法

LRU可以算是书本中比较熟悉的算法了,有缓存存在的场景下,基本都会有它的身影。它的作用就是在空间一定的缓存中,淘汰掉最近最少使用的数据,这样就有空间容纳新的数据。

那么假如需要设计一个类似LRU的算法,要支持获取数据get和插入数据put,并且要求时间复杂度在O(1)。

如果get返回-1,代表这个值不在缓存中,否则返回对应的值。

put(k,v)的操作,如果k在缓存中,那就更新。如果不存在就插入,如果缓存容量满了,就把最近没有使用过的数据删掉,再插入。

思路

要求时间复杂度O(1),说明查找的速度和插入的速度都必须很快。

我们还要维护一个最近最久未使用的数据,但是这个数据一旦被访问过,就不再是最近最久未使用的数据了。

结合这几个要求,链表应该是最符合的数据结构了,但是链表存在一个问题,查找的速度不是O(1)。那就再加一个Map,把所有的链表节点都放到Map中,这样查找的速度就是O(1)。

链表还必须是带尾指针的双向链表,这样删除的操作就会更加的方便。

class LRUCache {
    
    
//实现一个双向链表
public class DList{
    
    
       private Node ret;
       private int size;

       private Node tail;
       public DList(){
    
    
            this.ret = new Node(-1,-1);
            this.size=0;
       }

       public void addFirst(Node node){
    
    
            if(ret.next==null){
    
    
                ret.next = node;
                node.prev = ret;
                tail = node;
                size++;
                return;
            }
            Node p = ret.next;
            node.next =p;
            ret.next = node;
            p.prev = node;
            node.prev = ret;
            size++;
            return;
       }

       public void remove(Node node){
    
    
           if(node==tail){
    
    
               tail = tail.prev ;
           }
           Node p = node.prev;
           Node q = node.next;
           p.next = q;
           if(q!=null){
    
    
               q.prev = p;
           }
           size--;
       }

       public Node removeLast(){
    
    
           Node res = tail;
           remove(tail);
           return res;
       }
        public int size(){
    
    
           return this.size;
       }
   }

    public class Node {
    
    
        public int key, val;
        public Node next, prev;
        public Node(int k, int v) {
    
    
            this.key = k;
            this.val = v;
        }
   }

        private HashMap<Integer, Node> map;
        private int cap;
        private DList cache;
        public LRUCache(int capacity) {
    
    
            this.cap = capacity;
            this.map = new HashMap<>();
            this.cache = new DList();
        }

        public int get(int key) {
    
    
            if(!map.containsKey(key)){
    
    
                return -1;
            }
            Node node = map.get(key);
            int val = node.val;
            put(key,val);
            return val;
        }

        public void put(int key, int value) {
    
    
            Node x = new Node(key, value);
            if(map.containsKey(key)){
    
    
                cache.remove(map.get(key));
                cache.addFirst(x);
                map.put(key,x);
            }
            else{
    
    
                if(cap == cache.size()){
    
    
                    Node last = cache.removeLast();
                    map.remove(last.key);
                }
                cache.addFirst(x);
                map.put(key,x);
            }
        }
}

Tag

design LRU

猜你喜欢

转载自blog.csdn.net/edisonzhi/article/details/117622074