zoukankan      html  css  js  c++  java
  • 算法:LRU(最近最少使用)

    算法:LRU(最近最少使用)

    本文参考自小灰文章:https://mp.weixin.qq.com/s/B5xiVeW22ZumbI9KfrYJSg

    LRU算法

    什么是LRU算法

      LRU算法又称最近最少使用算法,它的基本思想是长期不被使用的数据,在未来被用到的几率也不大,所以当新的数据进来时我们可以优先把这些数据替换掉

      在LRU算法中,使用了一种有趣的数据结构,称为哈希链表。我们知道哈希表是由多个<Key,Value>对组成的,哈希链表是将这写节点链接起来,每一个节点都有一个前驱结点和后驱节点,就像双向链表中的节点一样。哈希表拥有了固定的排列顺序。

      

      基于哈希链表的有序性,我们就可以把<Key,Value>按照最后的使用时间来排列。

    LRU算法的基本思路

      假设我们使用哈希链表来缓存用户信息,目前缓存了4个用户,用户按照时间顺序从链表右端插入:

      

      情景一:当访问用户5时,由于哈希链表中没有用户5的数据,从数据库中读取出来插入到缓存中

      

      情景二:挡访问用户2时,由于哈希链表中有用户2的数据,我们把它掐断,放到链表最右段

      

      

      情景三:同情景二,这次访问用户4的数据

      

      情景四:当用户访问用户6,用户6在缓存中没有,需要插入到链表中,但此时链表长度已满,我们把最左端的用户删掉,然后插入用户6

      

    说明:我们仔细回顾一下,当缓存命中时,我们就把它放到最右端,也就是说排在右边的是最近被使用过的,那左边的当然是相对较少被访问过的,所以当缓存不命中的时候,我们就把最左边的剔除掉,所以这里就体现了最近最少使用的原则。

    LRU算法的基本实现

    public class LRUCache{
        private int limit;
        private HashMap<String,Node> hashMap;
        private Node head;
        private Node end;
    
        public LRUCache(int limit)
        {
            this.limit = limit;
            hashMap = new HashMap<String,Node>();
        }
    
        public String get(String key){
            Node node = hashMap.get(key);
            if(node ==null)
                return null;
            refreshNode(node);
            return node.value;
        }
    
        public void put(String key,String value){
            Node node = hashMap.get(key);
            if(node == null){
                if(hashMap.size()>=limit)
                {
                    String oldKey = removeNode(head);
                    hashMap.remove(oldKey);
                }
                node = new Node(key,value);
                addNode(node);
                hashMap.put(key,node)
            }else{
                node.value = value;
                refreshNode(node);
            }
        }
    
        public void remove(String key){
            Node node = hashMap.get(key);
            removeNode(node);
            hashMap.remove(key);
        }
    
    
        /**
         * 刷新刚被访问的节点位置
         */
        private void refreshNode(Node node)
        {
            if(node == end)
                return;
            removeNode(node);
            addNode(node);
        }
    
        
        /**
         * 删除节点
         */
    
        public String removeNode(Node node){
            if(node == end)
                //删除尾节点
                end = end.pre;
            else if(node ==head)
                //删除头节点
                head = head.next;
            else
                {
                    //移除中间节点
                    node.pre.next = node.next;
                    node.next.pre = node.pre;
                }
            return node.key;
        }
        
        /**
         * 尾部插入节点
         */
    
         public void addNode(Node node)
         {
            if(end!=null)
            {
                end.next = node;
                node.pre = end;
                node.next = null;
            }
            end = node;
            if(head == null)
                head = node;
         }
    
    }
  • 相关阅读:
    JQuery empty方法和remove方法的区别,使用remove清除之前的文本内容??
    乙_1023 组个最小数 (20分)
    乙_1022 D进制的A+B (20分)
    乙_1021 个位数统计 (15分)
    乙_1020 月饼 (25分)
    乙_1013 数素数 (20分)
    乙_1009 说反话 (20分)
    乙_1008 数组元素循环右移问题 (20分)
    乙_1007 素数对猜想 (20分)
    乙_1005 继续(3n+1)猜想 (25分)
  • 原文地址:https://www.cnblogs.com/MrSaver/p/10143375.html
Copyright © 2011-2022 走看看