当前位置: 首页 > news >正文

数据结构与算法之LRU: 实现 LRU 缓存算法功能 (Javascript版)

关于LRU缓存

  • LRU - Lease Recently Used 最近使用

  • 如果内存优先,只缓存最近使用的,删除 ‘沉睡’ 数据

  • 核心 api: get set

  • 分析

    • 使用哈希表来实现, O(1)
    • 必须是有序的,常用放在前面,沉睡放在后面, 即:有序,可排序
    • 这样 {} 不符合要求;Map是可以排序的,按照设置顺序
class LRUCache {private length: numberprivate data: Map<any, any> = new  Map()constructor(length: number) {if (length < 1) throw new Error('invalid length')this.length = length}set(key: any, value: any) {const data = this.dataif (data.has(key)) {data.delete(key)}data.set(key, value)if (data.size > this.length) {// 如果超出了容量,则删除 Map 最老的元素const delKey = data.keys().next().valuedata.delete(delKey)}}get(key: any): any {const data = this.dataif(!data.has(key)) return nullconst value = data.get(key)data.delete(key)data.set(key, value) // 保持最新的return value}
}const lruCache = new LRUCache(2)
lruCache.set(1, 1) // { 1=1 }
lruCache.set(2, 2) // { 1=1,  2=2 }
lruCache.get(1) // 1 {2=2, 1=1}
lruCache.set(3,3) // {1=1, 3=3}
lruCache.get(2) // null
lruCache.set(4,4) // {3=3, 4=4}
lruCache.get(1) // null
lruCache.get(3) // {4=4, 3=3}
lruCache.get(4) // 4 {3=3, 4=4}

不用 Map 如何实现 LRU 缓存

  • 注意:有序
  • 结合 Object + Array
  • 将Array改造成双向链表
const obj1 = {value: 1, key: 'a'}
const obj2 = {value: 2, key: 'b'}
const obj3 = {value: 3, key: 'c'}const data = [obj1, obj2, obj3]
const map =  {'a': obj1, 'b': obj2, 'c': obj3}
  • 上述数据结构很精妙
interface IListNode {value: anykey: stringprev?: IListNodenext?: IListNode
}export default class LRUCache {private length: numberprivate data: { [key: string]: IListNode } = {}private dataLength: number = 0private listHead: IListNode | null = nullprivate listTail: IListNode | null = nullconstructor(length: number) {if (length < 1) throw new Error('invalid length')}private moveToTail(curNode: IListNode) {const tail = this.listTailif (tail === curNode) return// 1. 让 pre next 断绝与 curNode的关系const preNode = curNode.prevconst nextNode = curNode.nextif (prevNode) {if (nextNode) {preNode.next = nextNode} else {delete prevNode.next}}if (nextNode) {if (prevNode) {nextNode.prev = prevNode} else {delete nextNode.prev}if (this.listHead === curNode) this.listHead = nextNode}// 2. 让 curNode 断绝与 prev, next的关系delete curNode.prevdelete curNode.next// 3. 在list 末尾重新建立 curNode 的新关系if (tail) {tail.next = curNodecurNode.prev = tail}this.listTail = curNode}private tryClean() {while(this.dataLength > this.length) {const head = ths.listHeadif (!head) throw new Error('head is null')const headNext = head.nextif (!headNext) throw new Error('headNext is null')// 1. 断绝head和next的关系delete headNext.prevdelete head.next// 2. 重新赋值 listHeadthis.listHead = headNext// 3. 清理 data, 重新计数delete this.data[head.key]this.dataLength -= 1}}get(key: string):any {const data = this.dataconst curNode  = data[key]if (!curNode) return nullif (this.listTail === curNode) {reutrn curNode.vlaue}// curNode 移动到末尾this.moveToTail(curNode)}set(key: string, value: any) {const data = this.dataconst curNode  = data[key]if (!curNode) {// 新增数据const newNode: IListNode = {key, value}// 移动到末尾this.moveToTail(newNode)data[key] = newNodethis.dataLength ++if (this.dataLength === 1) this.listHead = newNode} else {// 修改现有数据curNode.value = value// 移动到末尾this.moveToTail(curNode)}// 长度超过了,则需要清理this.tryClean()}
}

功能性测试

const lruCache = new LRUCache(2)
lruCache.set('1', 1) // { 1=1 }
lruCache.set('2', 2) // { 1=1,  2=2 }
lruCache.get('1') // 1 {2=2, 1=1}
lruCache.set('3',3) // {1=1, 3=3}
lruCache.get('2') // null
lruCache.set('4',4) // {3=3, 4=4}
lruCache.get('1') // null
lruCache.get('3') // {4=4, 3=3}
lruCache.get('4') // 4 {3=3, 4=4}
  • 数据结构设计:data 和 list 分别存储什么
  • 双向链表的操作非常繁琐,代码很容易写错, 不易调试
  • 链表 node 要存储 node.key, 否则需要遍历 data 删除

相关文章:

数据结构与算法之LRU: 实现 LRU 缓存算法功能 (Javascript版)

关于LRU缓存 LRU - Lease Recently Used 最近使用 如果内存优先&#xff0c;只缓存最近使用的&#xff0c;删除 ‘沉睡’ 数据 核心 api: get set 分析 使用哈希表来实现, O(1)必须是有序的&#xff0c;常用放在前面&#xff0c;沉睡放在后面, 即&#xff1a;有序&#xff0…...

Matlab | 基于二次谱提取地震数据的地震子波

本文通过地震数据二次谱求取地震子波谱&#xff0c;具体方法如下&#xff1a; MATLAB代码实现如下&#xff1a; function w SndSpecExtWavelet(x, M) % 功能&#xff1a;基于二次谱提取输入地震数据data的地震子波wavelet % Extracting Wavelet from Input Seismic Dat…...

利用远程IO模块,轻松驾驭食品包装生产的自动化

常见的自动化包装系统&#xff0c;它的核心部分通常由一系列高端设备组成&#xff0c;包括自动开箱机、自动封箱机、自动捆扎机、装箱机器人、码垛机器人等。这些设备协同工作&#xff0c;形成一条高效运转的生产线&#xff0c;从开箱到装箱&#xff0c;再到码垛&#xff0c;每…...

华为OD机考算法题:计算最大乘积

题目部分 题目计算最大乘积难度易题目说明给定一个元素类型为小写字符串的数组&#xff0c;请计算两个没有相同字符的元素长度乘积的最大值。 如果没有符合条件的两个元素&#xff0c;返回 0。输入描述输入为一个半角逗号分隔的小写字符串的数组&#xff0c;2< 数组长度<…...

用友 GRP-U8 存在sql注入漏洞复现

0x01 漏洞介绍 用友 GRP-U8 license_check.jsp 存在sql注入&#xff0c;攻击者可利用该漏洞执行任意SQL语句&#xff0c;如查询数据、下载数据、写入webshell、执行系统命令以及绕过登录限制等。 fofa&#xff1a;app”用友-GRP-U8” 0x02 POC: /u8qx/license_check.jsp?kj…...

vue页面el-tab控件标签栏加入按钮功能

vue页面el-tab控件标签栏加入按钮功能 显示效果为&#xff1a; <el-tabs v-model"activeName" type"border-card" style"margin-right:5px"><el-tab-pane label"模型管理" name"first"><span slot"l…...

vue3使用ref和reactive

Vue 3引入了两个新的API&#xff0c;ref和reactive&#xff0c;用于创建响应式对象。这两个方法都位于Vue.prototype上&#xff0c;因此可以在组件实例中直接使用。 ref ref函数用于创建一个响应式引用对象。这个函数可以接受一个普通的变量或对象作为参数&#xff0c;并返回…...

7 款用于解锁iPhone密码的苹果解锁软件

无法访问您的 iPhone 一定是最烦人的情况之一。 即使您以前从未遇到过这种情况&#xff0c;做好准备总是一个好主意&#xff0c;而不是在它发生时感到无助。事实上&#xff0c;这种情况经常发生并且可能有很多实例&#xff0c;例如忘记密码或购买锁定的二手 iPhone。 牢记 Ap…...

.jnlp

首先配置电脑的java环境。 百度搜索jre下载&#xff0c;会有很多结果&#xff0c;一般选择官网进行下载。 下载正确的jre版本。 我的电脑是windows 64位&#xff0c;根据你自己电脑的情况选择版本进行下载。不懂自己电脑是多少位的可以看下一步。 查看电脑是64位还是32…...

Linux启动之uboot分析

Linux启动之uboot分析 uboot是什么&#xff1f;一、补充存储器概念1.存储器种类1.norflash - 是非易失性存储器&#xff08;也就是掉电保存&#xff09;2.nandflash - 是非易失性存储器&#xff08;也就是掉电保存&#xff09;3.SRAM - 静态随机访问存储器 - Static Random Acc…...

element -plus table的二次封装

个人简介 博主写了对element-plus的表格和表单的封装 大家支持一下 [表格]https://gitee.com/childe-jia/table-vue3 [表单] https://gitee.com/childe-jia/form-render Introduction WHAT i-table 基于元素 element-plus&#xff0c;但不限于元素 element-plus 组件。在完…...

windows应用软件扫描报告 不告谱 要钱

chatGPT开路&#xff0c;帮找。 当你想要查找Windows软件的漏洞而不涉及查看源代码时&#xff0c;你可以使用一些专门设计用于扫描漏洞的工具。这些工具通常会检查已安装的软件和操作系统的漏洞&#xff0c;并提供建议或修补程序。以下是一些可以用于查找Windows软件漏洞的工具…...

世界前沿技术发展报告2023《世界航空技术发展报告》(七)机载系统与武器技术

&#xff08;七&#xff09;机载系统与武器技术 1.机载系统技术1.1 美国推进商用5G技术在航空装备中的应用1.2 人工智能技术在航空中的应用日益增多1.3 美国空军研究实验室推出综合座舱感知技术1.4 美国空军为固定翼飞机驾驶员选定新一代头盔1.5 美国DARPA探索通过机载光能量中…...

JAVA 学习笔记——抽象类

概念&#xff1a; 当定义一个类时&#xff0c;常常需要定义一些成员方法来描述类的行为特征&#xff0c;但有时这些方法的实现方式是无法确定的。 例如&#xff0c;前面在定义 Animal 类时&#xff0c;walk()方法用于描述动物的行走行为&#xff0c;但是针对不同的动物&#…...

磁盘调度算法之先来先服务(FCFS),最短寻找时间优先(SSTF),扫描算法(SCAN,电梯算法),LOOK调度算法

目录 1.一次磁盘读/写操作需要的时间1.寻找时间2.延迟时间3.传输时间4.影响读写操作的因素 2.磁盘调度算法1.先来先服务(FCFS)1.例题2.优缺点 2.最短寻找时间优先(SSTF)1.例题2.优缺点3.饥饿的原因 3.扫描算法(SCAN)1.例题2.优缺点 4.LOOK调度算法1.例题2.优点 5.循环扫描算法(…...

postman接口测试—Restful接口开发与测试

开发完接口&#xff0c;接下来我们需要对我们开发的接口进行测试。接口测试的方法比较多&#xff0c;使用接口工具或者Python来测试都可以&#xff0c;工具方面比如之前我们学习过的Postman或者Jmeter &#xff0c;Python脚本测试可以使用Requests unittest来测试。 测试思路…...

RK3568-emmc控制器

emmc控制器 eMMC主机控制器具有高度的可配置性和可编程性&#xff0c;并提供高性能的eMMC主机控制器&#xff0c;以AXI作为数据传输的总线接口&#xff08;主接口&#xff09;&#xff0c;以AHB作为其从接口。 它支持以下功能&#xff1a; - 支持SD-HCI主机版本4模式或更少的 …...

02-操作符及类型转换与控制流程语句

操作符及类型转换与控制流程语句 1.操作符1.1.算数运算符正常的数据运算进行数据运算时&#xff0c;除外&#xff0c;其他运算符可以自动将字符串数字隐形转成数字 1.2.一元运算符JavaScript中有8种常用的一元运算符 (正号)1.的第一种用法:进行数据相加2.放在数据的前面&#…...

判断一个字符串中是否包含中文字符

下面我将为你提供三种常用的方法&#xff1a; 方法一&#xff1a;使用正则表达式 import java.util.regex.Pattern; import java.util.regex.Matcher;public class ChineseCharacterChecker {public static boolean containsChineseCharacters(String input) {String regex …...

软件测试面试怎样介绍自己的测试项目?会问到什么程度?

想知道面试时该怎样介绍测试项目&#xff1f;会问到什么程度&#xff1f;那就需要换位思考&#xff0c;思考HR在这个环节想知道什么。 HR在该环节普遍想获得的情报主要是下面这2个方面&#xff1a; 1&#xff09;应聘者的具体经验和技术能力&#xff0c; 2&#xff09;应聘者的…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...