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());
    }
}


参考资料




相关文章
|
1月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
60 4
|
1月前
|
机器学习/深度学习 算法 Python
探索机器学习中的决策树算法:从理论到实践
【10月更文挑战第5天】本文旨在通过浅显易懂的语言,带领读者了解并实现一个基础的决策树模型。我们将从决策树的基本概念出发,逐步深入其构建过程,包括特征选择、树的生成与剪枝等关键技术点,并以一个简单的例子演示如何用Python代码实现一个决策树分类器。文章不仅注重理论阐述,更侧重于实际操作,以期帮助初学者快速入门并在真实数据上应用这一算法。
|
1月前
|
机器学习/深度学习 人工智能 Rust
MindSpore QuickStart——LSTM算法实践学习
MindSpore QuickStart——LSTM算法实践学习
40 2
|
1月前
|
机器学习/深度学习 算法 数据建模
计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践
计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践
30 0
|
3月前
|
缓存 算法 前端开发
深入理解缓存淘汰策略:LRU和LFU算法的解析与应用
【8月更文挑战第25天】在计算机科学领域,高效管理资源对于提升系统性能至关重要。内存缓存作为一种加速数据读取的有效方法,其管理策略直接影响整体性能。本文重点介绍两种常用的缓存淘汰算法:LRU(最近最少使用)和LFU(最不经常使用)。LRU算法依据数据最近是否被访问来进行淘汰决策;而LFU算法则根据数据的访问频率做出判断。这两种算法各有特点,适用于不同的应用场景。通过深入分析这两种算法的原理、实现方式及适用场景,本文旨在帮助开发者更好地理解缓存管理机制,从而在实际应用中作出更合理的选择,有效提升系统性能和用户体验。
194 1
|
3月前
|
DataWorks 算法 调度
B端算法实践问题之配置脚本以支持blink批处理作业的调度如何解决
B端算法实践问题之配置脚本以支持blink批处理作业的调度如何解决
43 1
|
3月前
|
SQL 算法 Serverless
B端算法实践问题之使用concat_id算子获取用户最近点击的50个商品ID如何解决
B端算法实践问题之使用concat_id算子获取用户最近点击的50个商品ID如何解决
28 1
|
3月前
|
存储 SQL 消息中间件
B端算法实践问题之设计一套实时平台能力如何解决
B端算法实践问题之设计一套实时平台能力如何解决
42 1
|
3月前
|
存储 SQL 算法
B端算法实践问题之Blink在实时业务场景下的优势如何解决
B端算法实践问题之Blink在实时业务场景下的优势如何解决
47 1
下一篇
无影云桌面