缓存淘汰(LRU)算法

LRU(最近最少使用)算法是一种常见的缓存淘汰策略,广泛应用于操作系统、数据库缓存、网页缓存等领域。该算法的核心思想是优先淘汰那些最长时间未被使用的数据,基于的假设是如果数据最近被访问过,那么将来被访问的可能性也更高。

LRU 算法的工作原理

  1. 数据结构

    • LRU算法通常利用一个双向链表(Linked List)和一个哈希表(Hash Map)来实现。链表用于表示缓存中的数据顺序,其中最近使用的数据排在链表头部,最久未使用的数据排在链表尾部。哈希表则存储每个数据的键与其在链表中的节点的对应关系,以支持快速的查找和更新操作。
  2. 访问数据

    • 当一个数据被访问时,如果数据在缓存中(哈希表能够找到),则将这个数据对应的节点在链表中移动到链表头部,表示最近被访问过。
    • 如果数据不在缓存中,需要将数据加载到缓存。如果此时缓存未满,可以直接添加到链表头部并更新哈希表。如果缓存已满,则需要从链表尾部移除最久未使用的数据,并把新数据添加到链表头部。
  3. 淘汰数据

    • 当需要空间来存储新的数据时,算法会从链表的尾部移除最久未被访问的数据节点,并同步从哈希表中删除相应的键值对。

实现示例

在Java中实现LRU缓存,可以使用一个双向链表来跟踪最近最少使用的元素,同时使用一个哈希表来实现快速查找。下面是一个简单的Java实现示例:

首先,定义一个双向链表节点的类,该类包含键、值以及指向前一个节点和后一个节点的指针:

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

然后,定义LRU缓存类,其中包含添加节点、移除节点、移动节点到头部、弹出尾部节点的方法,以及一个用于存储节点的哈希表和维护节点顺序的双向链表:

import java.util.HashMap;public class LRUCache {private HashMap<Integer, Node> map;private int capacity, count;private Node head, tail;public LRUCache(int capacity) {this.capacity = capacity;map = new HashMap<>();head = new Node(0, 0);tail = new Node(0, 0);head.next = tail;tail.prev = head;head.prev = null;tail.next = null;count = 0;}public void deleteNode(Node node) {node.prev.next = node.next;node.next.prev = node.prev;}public void addToHead(Node node) {node.next = head.next;node.next.prev = node;node.prev = head;head.next = node;}public int get(int key) {if (map.containsKey(key)) {Node node = map.get(key);deleteNode(node);addToHead(node);return node.value;}return -1;}public void put(int key, int value) {if (map.containsKey(key)) {Node node = map.get(key);node.value = value;deleteNode(node);addToHead(node);} else {Node node = new Node(key, value);map.put(key, node);if (count < capacity) {count++;addToHead(node);} else {map.remove(tail.prev.key);deleteNode(tail.prev);addToHead(node);}}}
}

在这个实现中:

  • Node 类定义了链表的节点。
  • LRUCache 类包括一个哈希表和一个双向链表。get 方法和 put 方法实现了LRU缓存的核心功能。
  • addToHeaddeleteNode 方法用于节点的添加和删除操作。

这种结构确保了 getput 操作的时间复杂度为 O(1),即常数时间复杂度,因为它们主要依赖于哈希表的操作和几个指针的改动。

总结

LRU缓存算法通过维护一个记录访问历史的列表来决定哪个数据项淘汰,使得长时间未被访问的数据最先被移除,这样可以有效地利用有限的缓存空间,确保缓存的高效使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/11793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

英伟达科学家展望:OpenAI或将引领AI多模态语音助手新时代

在人工智能领域,语音助手一直是人们关注的焦点。随着技术的不断发展,从简单的语音指令识别到复杂的对话系统,语音AI正逐渐融入我们的日常生活。今晚凌晨2点,OpenAI可能发布的AI多模态语音助手无疑将再次引发业界的热烈讨论。英伟达科学家KOL近日对此进行了深入解读,为我们…

永嘉原厂8×16点阵数码管驱动抗干扰数码管驱动IC防干扰数显芯片VK1640 SOP28

产品型号&#xff1a;VK1640 产品品牌&#xff1a;永嘉微电/VINKA 封装形式&#xff1a;SOP28 原厂&#xff0c;工程服务&#xff0c;技术支持&#xff01; 概述 VK1640是一种数码管或点阵LED驱动控制专用芯片&#xff0c;内部集成有数据锁存器、LED 驱动等电路。SEG脚接LE…

网络安全快速入门(十二) linux的目录结构

我们前面已经了解了基础命令&#xff0c;今天我们来讲讲linux中的目录结构&#xff0c;我们在了解linux的目录结构之前&#xff0c;我们先与Windows做一个对比 12.1linux和windows的目录结构对比 在之前认识liunx的章节中&#xff0c;我们已经简单说明了linux和window的目录结构…

day2 leecode88 合并两个有序数组

leetcode88合并两个有序数组 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 **注意&#xf…

Java面试八股之String类的常用方法有哪些

Java中String类的常用方法有哪些 获取字符串信息&#xff1a; length()&#xff1a;返回字符串的字符数。 isEmpty()&#xff1a;判断字符串是否为空&#xff08;即长度为0&#xff09;。 访问单个字符&#xff1a; charAt(int index)&#xff1a;返回指定索引处的字符。 …

射频识别技术初探

射频识别技术 引言RFID的构成RFID标签读写器天线中间件应用软件RFID的工作流程RFID标准ISO/IEC RFID 标准体系RFID的数据传输原理RFID的编码方式引言 射频识别技术是一种无线通信识别技术,通过无线电信号识别特定目标并读取相关数据,而无需建立专门的机械或光学接触。 无线…

Mamba:6 线性RNN

若在阅读过程中有些知识点存在盲区&#xff0c;可以回到如何优雅的谈论大模型重新阅读。另外斯坦福2024人工智能报告解读为通识性读物。若对于如果构建生成级别的AI架构则可以关注AI架构设计。技术宅麻烦死磕LLM背后的基础模型。当然最重要的是订阅跟随“鲁班模锤”。 Mamba自从…

mapreduce的优化方法

1、数据输入 &#xff08;1&#xff09;合并小文件&#xff1a;在执行mr任务前将小文件进行合并&#xff0c;大量的小文件会产生大量的map任务&#xff0c;增大map任务装载次数 &#xff0c;而任务的装载比较耗时 &#xff0c;从而导致 mr 运行较慢。 &#xff08;2&#xff09…

YOLO数据集制作(四)|json文件转txt验证(多边形框)

以下教程用于验证转成YOLO使用的txt格式&#xff0c;适用场景&#xff1a;多边形框&#xff0c;配合json格式文件转成YOLO使用的txt格式脚本使用。 YOLO数据集制作&#xff08;三&#xff09;|Labelme标注的“多边形框”json文件转txt-CSDN博客 使用方式&#xff1a;将img_pa…

简单实现---基于STL的演讲比赛流程管理系统(C++实现)

前言 事先声明&#xff1a;本文章中编写的代码仅用于学习算法思想和编写基础形式使用&#xff0c;并未进行太多的代码优化&#xff0c;因此&#xff0c;若需要对代码进行优化以及异常处理的小伙伴们&#xff0c;可自行添加相关操作&#xff0c;谢谢&#xff01; 一、题…

探索Linux中的cd和pwd命令:理解与应用

探索Linux中的cd和pwd命令&#xff1a;理解与应用 在Linux操作系统中&#xff0c;cd和pwd是两个非常基础但又非常重要的命令。它们分别用于改变当前工作目录和显示当前工作目录的路径。本文将深入探讨这两个命令的用法&#xff0c;并结合实例进行解释&#xff0c;帮助读者更好…

如何创建 Ansible Playbooks 来自动化 Ubuntu 系统配置

介绍 Ansible 是一个简单的配置管理系统&#xff0c;可用于自动化和组织大型计算机网络的系统配置任务。虽然其他一些配置管理系统需要在服务器和客户端系统上安装许多不同的软件包&#xff0c;但使用 Ansible 只需要安装一个服务器组件并且具有对客户端机器的 SSH 访问权限。 …

数据结构与算法学习笔记四---双向链表的表示和实现(C语言)

1.前言 这篇文章主要介绍双向链表的表示和实现。 2.双向链表 单链表中只有一个指示直接后继的指针域&#xff0c;由此&#xff0c;从某个结点出发只能顺指针向后寻查其他结点。若要寻查结点的直接前驱&#xff0c;则必须从表头指针出发。换句话说&#xff0c;在单链表中&#…

​​​【收录 Hello 算法】第 6 章 哈希表

目录 第 6 章 哈希表 本章内容 第 6 章 哈希表 Abstract 在计算机世界中&#xff0c;哈希表如同一位聪慧的图书管理员。 他知道如何计算索书号&#xff0c;从而可以快速找到目标图书。 本章内容 6.1 哈希表6.2 哈希冲突6.3 哈希算法6.4 小结

日志:打印技巧

一、概览 Unity日志打印技巧 常规日志打印彩色日志日志存储与上传日志开关日志双击溯源 二、常规日志打印 1、打印Hello World 调用堆栈可以很好的帮助我们定位问题&#xff0c;特别是报错的Error日志 Debug.Log("Hello World");Debug.Log("This is a log m…

【java】代理

什么是代理 假设有一个核心方法叫转账&#xff0c;为了安全性考虑&#xff0c;不能让用户直接访问接口。此时涉及到了代理&#xff0c;这使得用户只能访问代理类&#xff0c;增加了访问限制。 代理的定义&#xff1a;给目标对象提供一个代理对象&#xff0c;并且由代理对象控…

egg.socket.io后端开发

1. 安装egg-socket.io npm i egg-socket.io4.1.6 --save最好指定egg-socket.io的版本号&#xff0c;比如我后端使用"egg-socket.io": "^4.1.6", 因为跟前端的socket.io-client是一一关联&#xff0c;socket.io-client用高版本或低版本&#xff0c;都不兼容…

果蔬经营平台|基于SSM+vue的果蔬经营平台系统的设计与实现(源码+数据库+文档)

果蔬经营平台系统 目录 基于SSM&#xff0b;vue的果蔬经营平台系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介…

Python面试50题!面试巩固必看!

题目001: 在Python中如何实现单例模式。 点评&#xff1a;单例模式是指让一个类只能创建出唯一的实例&#xff0c;这个题目在面试中出现的频率极高&#xff0c;因为它考察的不仅仅是单例模式&#xff0c;更是对Python语言到底掌握到何种程度&#xff0c;建议大家用装饰器和元类…

【卫星影像三维重建-全流程代码实现】点云Mesh重构

点云—>Mesh模型 1.介绍1.1 背景1.2 效果示意 2 算法实现2.1 依赖库2.2 实验数据2.3 代码实现2.4 实验效果 3.总结 1.介绍 1.1 背景 &#xff08;1&#xff09;本文主要内容是将三维点云&#xff08;离散的三维点&#xff09;进行表面重建生成Mesh网格&#xff0c;之前有篇…