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


参考资料




相关文章
|
3月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
120 3
|
1月前
|
机器学习/深度学习 人工智能 算法
深入解析图神经网络:Graph Transformer的算法基础与工程实践
Graph Transformer是一种结合了Transformer自注意力机制与图神经网络(GNNs)特点的神经网络模型,专为处理图结构数据而设计。它通过改进的数据表示方法、自注意力机制、拉普拉斯位置编码、消息传递与聚合机制等核心技术,实现了对图中节点间关系信息的高效处理及长程依赖关系的捕捉,显著提升了图相关任务的性能。本文详细解析了Graph Transformer的技术原理、实现细节及应用场景,并通过图书推荐系统的实例,展示了其在实际问题解决中的强大能力。
232 30
|
1月前
|
存储 算法
深入解析PID控制算法:从理论到实践的完整指南
前言 大家好,今天我们介绍一下经典控制理论中的PID控制算法,并着重讲解该算法的编码实现,为实现后续的倒立摆样例内容做准备。 众所周知,掌握了 PID ,就相当于进入了控制工程的大门,也能为更高阶的控制理论学习打下基础。 在很多的自动化控制领域。都会遇到PID控制算法,这种算法具有很好的控制模式,可以让系统具有很好的鲁棒性。 基本介绍 PID 深入理解 (1)闭环控制系统:讲解 PID 之前,我们先解释什么是闭环控制系统。简单说就是一个有输入有输出的系统,输入能影响输出。一般情况下,人们也称输出为反馈,因此也叫闭环反馈控制系统。比如恒温水池,输入就是加热功率,输出就是水温度;比如冷库,
410 15
|
3月前
|
机器学习/深度学习 算法 Python
探索机器学习中的决策树算法:从理论到实践
【10月更文挑战第5天】本文旨在通过浅显易懂的语言,带领读者了解并实现一个基础的决策树模型。我们将从决策树的基本概念出发,逐步深入其构建过程,包括特征选择、树的生成与剪枝等关键技术点,并以一个简单的例子演示如何用Python代码实现一个决策树分类器。文章不仅注重理论阐述,更侧重于实际操作,以期帮助初学者快速入门并在真实数据上应用这一算法。
|
3月前
|
机器学习/深度学习 人工智能 Rust
MindSpore QuickStart——LSTM算法实践学习
MindSpore QuickStart——LSTM算法实践学习
70 2
|
3月前
|
机器学习/深度学习 算法 数据建模
计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践
计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践
56 0
|
4月前
|
数据采集 算法 物联网
【算法精讲系列】阿里云百炼SFT微调实践分享
本内容为您提供了百炼平台SFT微调的实践案例,帮助您方便并快速借助模型微调定制化您自己的专属模型。
|
5月前
|
缓存 算法 前端开发
深入理解缓存淘汰策略:LRU和LFU算法的解析与应用
【8月更文挑战第25天】在计算机科学领域,高效管理资源对于提升系统性能至关重要。内存缓存作为一种加速数据读取的有效方法,其管理策略直接影响整体性能。本文重点介绍两种常用的缓存淘汰算法:LRU(最近最少使用)和LFU(最不经常使用)。LRU算法依据数据最近是否被访问来进行淘汰决策;而LFU算法则根据数据的访问频率做出判断。这两种算法各有特点,适用于不同的应用场景。通过深入分析这两种算法的原理、实现方式及适用场景,本文旨在帮助开发者更好地理解缓存管理机制,从而在实际应用中作出更合理的选择,有效提升系统性能和用户体验。
267 1
|
5月前
|
DataWorks 算法 调度
B端算法实践问题之配置脚本以支持blink批处理作业的调度如何解决
B端算法实践问题之配置脚本以支持blink批处理作业的调度如何解决
58 1