LRU 算法实践(下)

简介: LRU 算法实践

实现案例二


不依赖 jdk


数据结构示意:


image.png


思路解释:


1、 参照 HashMap 的做法先创建一个, Node 节点对象,包含 k, v 属性 和前驱,后继对象指针。


2、 构建一个双端链表 DoubleLinkList 实现缓存数据链表结构。主要包含 addHead 添加到头节点,作用是用来更新新访问的 Node, 还有一个就是 removeNode 删除节点。以及 getLastNode 获取尾部节点。


3、通过 MapDoubleLinkList 联合起来共同组建一个 LRU 结构。整体如上图所示


public class Q149_1 {
    // map 负责查找,构建一个虚拟的双向链表, 它里面安装的就是一个 Node 节点,作为数据的载体
    // 1 构造一个 Node 节点,作为数据的载体
    class Node<K, V> {
        K key;
        V value;
        Node<K, V> prev;
        Node<K, V> next;
        public Node() {
            this.prev = this.next = null;
        }
        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.prev = this.next = null;
        }
    }
    //2 构建一个双向队列,里面存放的就是我们的 Node
    class DoubleLinkList<K, V> {
        Node<K, V> head;
        Node<K, V> tail;
        // 2.1 构造方法
        public DoubleLinkList() {
            this.head = new Node<>();
            this.tail = new Node<>();
            this.head.next = this.tail;
            this.tail.prev = this.head;
        }
        // 2.2 添加到头
        public void addHead(Node<K, V> node) {
            node.next = head.next;
            node.prev = head;
            head.next.prev = node;
            head.next = node;
        }
        //2.3  删除节点
        public void removeNode(Node<K, V> node) {
            node.next.prev = node.prev;
            node.prev.next = node.next;
            node.prev = null;
            node.next = null;
        }
        //2.4 获得最后一个节点
        public Node<K, V> getLast() {
            return tail.prev;
        }
    }
    private int cacheSize;
    private Map<Integer, Node<Integer, Integer>> map;
    private DoubleLinkList<Integer, Integer> doubleLinkList;
    public Q149_1(int cacheSize) {
        this.cacheSize = cacheSize;
        this.map = new HashMap<>();
        doubleLinkList = new DoubleLinkList<>();
    }
    public int get(int key) {
        if (!map.containsKey(key)) {
            return -1;
        }
        Node<Integer, Integer> node = map.get(key);
        doubleLinkList.removeNode(node);
        doubleLinkList.addHead(node);
        return node.value;
    }
    // save of update method
    public void put(int key, int value) {
        // update
        if (map.containsKey(key)) {
            Node<Integer, Integer> node = map.get(key);
            node.value = value;
            map.put(key, node);
            doubleLinkList.removeNode(node);
            doubleLinkList.addHead(node);
        } else {
            if (map.size() == cacheSize) {
                Node<Integer, Integer> lastNode = doubleLinkList.getLast();
                map.remove(lastNode.key);
                doubleLinkList.removeNode(lastNode);
            }
            // 新增
            Node<Integer, Integer> newNode = new Node<>(key, value);
            map.put(key, newNode);
            doubleLinkList.addHead(newNode);
        }
    }
    public static void main(String[] args) {
        Q149_1 q149 = new Q149_1(3);
        q149.put(1, 1);
        q149.put(2, 2);
        q149.put(3, 3);
        System.out.println(q149.map.keySet());
        q149.put(1, 2);
        q149.put(2, 1);
        System.out.println(q149.map.keySet());
    }
}


参考资料




相关文章
|
2天前
|
存储 缓存 算法
LRU(Least Recently Used)算法原理
LRU(Least Recently Used)算法原理
3 0
|
2天前
|
机器学习/深度学习 搜索推荐 算法
推荐系统的算法与实现:深入解析与实践
【6月更文挑战第14天】本文深入探讨了推荐系统的原理与实现,包括用户和项目建模、协同过滤、内容过滤及混合推荐算法。通过收集用户行为数据,系统预测用户兴趣,提供个性化推荐。实践中,涉及数据处理、建模、算法选择及结果优化。随着技术发展,推荐系统将持续改进,提升性能和用户体验。
|
6天前
|
算法 数据挖掘 定位技术
算法必备数学基础:图论方法由浅入深实践与应用
算法必备数学基础:图论方法由浅入深实践与应用
|
6天前
|
存储 算法 数据挖掘
螺旋矩阵 II:从理论到实践的五种算法解析
螺旋矩阵 II:从理论到实践的五种算法解析
|
30天前
|
缓存 算法 Java
数据结构~缓存淘汰算法--LRU算法(Java的俩种实现方式,万字解析
数据结构~缓存淘汰算法--LRU算法(Java的俩种实现方式,万字解析
|
30天前
|
缓存 算法 前端开发
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
|
1月前
|
缓存 监控 算法
如何调整InnoDB的LRU算法以提高效率?
【5月更文挑战第14天】如何调整InnoDB的LRU算法以提高效率?
16 2
|
1月前
|
缓存 算法
LRU(Least Recently Used)算法是一种常用的计算机缓存替换算法
【5月更文挑战第4天】LRU算法是基于页面使用频率的缓存策略,优先淘汰最近最久未使用的页面。实现可采用双向链表或数组,前者灵活,后者时间复杂度低。优点是利用时间局部性提高命中率,简单易实现;缺点是占用空间,对循环访问和随机访问场景适应性不佳。
43 0
|
1月前
|
机器学习/深度学习 运维 算法
【Python机器学习专栏】异常检测算法在Python中的实践
【4月更文挑战第30天】本文介绍了异常检测的重要性和在不同领域的应用,如欺诈检测和网络安全。文章概述了四种常见异常检测算法:基于统计、距离、密度和模型的方法。在Python实践中,使用scikit-learn库展示了如何实现这些算法,包括正态分布拟合、K-means聚类、局部异常因子(LOF)和孤立森林(Isolation Forest)。通过计算概率密度、距离、LOF值和数据点的平均路径长度来识别异常值。
|
1月前
|
存储 缓存 算法
面试遇到算法题:实现LRU缓存
V哥的这个实现的关键在于维护一个双向链表,它可以帮助我们快速地访问、更新和删除最近最少使用的节点,同时使用哈希表来提供快速的查找能力。这样,我们就可以在 O(1) 的时间复杂度内完成所有的缓存操作。哈哈干净利索,回答完毕。