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

    LRU算法实现

    以下是基于 双向链表 + HashMap 的 LRU 算法实现,对算法的解释如下:

    访问某个节点时,将其从原来的位置删除,并重新插入到链表头部。这样就能保证链表尾部存储的就是最近最久未使用的节点,当节点数量大于缓存最大空间时就淘汰链表尾部的节点。
    为了使删除操作时间复杂度为 O(1),就不能采用遍历的方式找到某个节点。HashMap 存储着 Key 到节点的映射,通过 Key 就能以 O(1) 的时间得到节点,然后再以 O(1) 的时间将其从双向队列中删除。

    
    public class LRU<K, V> implements Iterable<K> {
    
        private Node head;
        private Node tail;
        private HashMap<K, Node> map;
        private int maxSize;
    
        private class Node {
    
            Node pre;
            Node next;
            K k;
            V v;
    
            public Node(K k, V v) {
                this.k = k;
                this.v = v;
            }
        }
    
    
        public LRU(int maxSize) {
    
            this.maxSize = maxSize;
            this.map = new HashMap<>(maxSize * 4 / 3);
    
            head = new Node(null, null);
            tail = new Node(null, null);
    
            head.next = tail;
            tail.pre = head;
        }
    
    
        public V get(K key) {
    
            if (!map.containsKey(key)) {
                return null;
            }
    
            Node node = map.get(key);
            unlink(node);
            appendHead(node);
    
            return node.v;
        }
    
    
        public void put(K key, V value) {
    
            if (map.containsKey(key)) {
                Node node = map.get(key);
                unlink(node);
            }
    
            Node node = new Node(key, value);
            map.put(key, node);
            appendHead(node);
    
            if (map.size() > maxSize) {
                Node toRemove = removeTail();
                map.remove(toRemove.k);
            }
        }
    
    
        private void unlink(Node node) {
    
            Node pre = node.pre;
            Node next = node.next;
    
            pre.next = next;
            next.pre = pre;
    
            node.pre = null;
            node.next = null;
        }
    
    
        private void appendHead(Node node) {
            Node next = head.next;
            node.next = next;
            next.pre = node;
            node.pre = head;
            head.next = node;
        }
    
    
        private Node removeTail() {
    
            Node node = tail.pre;
    
            Node pre = node.pre;
            tail.pre = pre;
            pre.next = tail;
    
            node.pre = null;
            node.next = null;
    
            return node;
        }
    
    
        @Override
        public Iterator<K> iterator() {
    
            return new Iterator<K>() {
                private Node cur = head.next;
    
                @Override
                public boolean hasNext() {
                    return cur != tail;
                }
    
                @Override
                public K next() {
                    Node node = cur;
                    cur = cur.next;
                    return node.k;
                }
            };
        }
    }
    

    转载自:https://github.com/CyC2018/CS-Notes/blob/master/notes/%E7%BC%93%E5%AD%98.md

  • 相关阅读:
    php模式设计之 工厂模式
    SDK以及部署的SDK的思路
    手机用fiddler抓包开发测试
    搭建GIT服务端
    TP5.0以上数据库增加数据异常
    lnmp一键安装后的配置改动建议
    TPshop5最新版 安装 nginx 开启PATHINFO 模式资源加载路径加载失败问题,适用tp3.2PATHINFO模式REWRITE模式
    jquery写拉动条
    JS(JQ)分页 个人查看,没注释
    ecshop 分页
  • 原文地址:https://www.cnblogs.com/DiZhang/p/12544759.html
Copyright © 2011-2022 走看看