zoukankan      html  css  js  c++  java
  • 【数据结构】算法设计 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

  • 相关阅读:
    为什么比特币和以太坊未必真得比EOS更去中心化?
    为什么我说IPFS社区从卖矿机开始,就是错的
    人群捕捞,不知不觉控制你
    Maven解决repository不更换的问题
    Ubuntu安装mysql-proxy
    Ubuntu的NTP同步时钟设置方法
    MySQL索引原理及慢查询优化
    MySQL对比清除不必要的表
    MySQL5.7绿色版安装
    Ubuntu下监控服务
  • 原文地址:https://www.cnblogs.com/dreamtaker/p/14854881.html
Copyright © 2011-2022 走看看