首页 > 编程语言 > 详细

【数据结构】算法设计 LRU Least Recently Used 最近最少使用算法

时间:2021-06-06 13:22:18      阅读:12      评论:0      收藏:0      [点我收藏+]

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

【数据结构】算法设计 LRU Least Recently Used 最近最少使用算法

原文:https://www.cnblogs.com/dreamtaker/p/14854881.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!