zoukankan      html  css  js  c++  java
  • LRU算法

    LRU 缓存淘汰算法就是一种常用策略, LRU 的全称是 Least Recently Used,也就是说我们认为最近使用过的数据应该是是「有用的」,很久都没用过的数据应该是无用的,内存满了就优先删那些很久没用过的数据。

    1、如果我们每次默认从链表尾部添加元素,那么显然越靠尾部的元素就是最近使用的,越靠头部的元素就是最久未使用的。

    2、对于某一个 key,我们可以通过哈希表快速定位到链表中的节点,从而取得对应 val

    3、链表显然是支持在任意位置快速插入和删除的,改改指针就行。只不过传统的链表无法按照索引快速访问某一个位置的元素,而这里借助哈希表,可以通过 key 快速映射到任意一个链表节点,然后进行插入和删除。

    代码实现:

    节点:

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

    双向链表:

    class DoubleList {  
        // 头尾虚节点
        private Node head, tail;  
        // 链表元素数
        private int size;
        
        public DoubleList() {
            // 初始化双向链表的数据
            head = new Node(0, 0);
            tail = new Node(0, 0);
            head.next = tail;
            tail.prev = head;
            size = 0;
        }
    
        // 在链表尾部添加节点 x,时间 O(1)
        public void addLast(Node x) {
            x.prev = tail.prev;
            x.next = tail;
            tail.prev.next = x;
            tail.prev = x;
            size++;
        }
    
        // 删除链表中的 x 节点(x 一定存在)
        // 由于是双链表且给的是目标 Node 节点,时间 O(1)
        public void remove(Node x) {
            x.prev.next = x.next;
            x.next.prev = x.prev;
            size--;
        }
        
        // 删除链表中第一个节点,并返回该节点,时间 O(1)
        public Node removeFirst() {
            if (head.next == tail)
                return null;
            Node first = head.next;
            remove(first);
            return first;
        }
    
        // 返回链表长度,时间 O(1)
        public int size() { return size; }
    
    }

    调用:

    class LRUCache {
        // key -> Node(key, val)
        private HashMap<Integer, Node> map;
        // Node(k1, v1) <-> Node(k2, v2)...
        private DoubleList cache;
        // 最大容量
        private int cap;
    
        public LRUCache(int capacity) {
            this.cap = capacity;
            map = new HashMap<>();
            cache = new DoubleList();
        }
    
        public int get(int key) {
            if (!map.containsKey(key)) {
                return -1;
            }
            // 将该数据提升为最近使用的
            makeRecently(key);
            return map.get(key).val;
        }
    
        public void put(int key, int val) {
            if (map.containsKey(key)) {
                // 删除旧的数据
                deleteKey(key);
                // 新插入的数据为最近使用的数据
                addRecently(key, val);
                return;
            }
    
            if (cap == cache.size()) {
                // 删除最久未使用的元素
                removeLeastRecently();
            }
            // 添加为最近使用的元素
            addRecently(key, val);
        }
    
    
        /* 将某个 key 提升为最近使用的 */
        private void makeRecently(int key) {
            Node x = map.get(key);
            // 先从链表中删除这个节点
            cache.remove(x);
            // 重新插到队尾
            cache.addLast(x);
        }
    
        /* 添加最近使用的元素 */
        private void addRecently(int key, int val) {
            Node x = new Node(key, val);
            // 链表尾部就是最近使用的元素
            cache.addLast(x);
            // 别忘了在 map 中添加 key 的映射
            map.put(key, x);
        }
    
        /* 删除某一个 key */
        private void deleteKey(int key) {
            Node x = map.get(key);
            // 从链表中删除
            cache.remove(x);
            // 从 map 中删除
            map.remove(key);
        }
    
        /* 删除最久未使用的元素 */
        private void removeLeastRecently() {
            // 链表头部的第一个元素就是最久未使用的
            Node deletedNode = cache.removeFirst();
            // 同时别忘了从 map 中删除它的 key
            int deletedKey = deletedNode.key;
            map.remove(deletedKey);
        }
    
    
    
    }
  • 相关阅读:
    摇骰子游戏
    那些年,产品提出的无理需求
    cookie中数据无法读取,HttpOnly属性
    vue 使用字典值及其翻译
    微信小程序picker组件两列关联使用方式
    fatal: unable to access 'https://github.com/xxxxxgit/': OpenSSL SSL_connect: Connection was reset in connection to github.com:443
    Oracle数据库以date类型保存日期时 nvalid request: Out of range property; SalesOrder.date'
    Event Handler Content must support at least one class.
    Minimum length not met: value 0 < 1 minimum length
    Oracle中使用hash_hmac() 函数报错问题/以及Oracle遇到Oauth1.0授权和oauth_signature生成规则
  • 原文地址:https://www.cnblogs.com/jiefangzhe/p/15075109.html
Copyright © 2011-2022 走看看