数据结构与算法之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 最近使用 如果内存优先,只缓存最近使用的,删除 ‘沉睡’ 数据 核心 api: get set 分析 使用哈希表来实现, O(1)必须是有序的,常用放在前面,沉睡放在后面, 即:有序࿰…...
Matlab | 基于二次谱提取地震数据的地震子波
本文通过地震数据二次谱求取地震子波谱,具体方法如下: MATLAB代码实现如下: function w SndSpecExtWavelet(x, M) % 功能:基于二次谱提取输入地震数据data的地震子波wavelet % Extracting Wavelet from Input Seismic Dat…...
利用远程IO模块,轻松驾驭食品包装生产的自动化
常见的自动化包装系统,它的核心部分通常由一系列高端设备组成,包括自动开箱机、自动封箱机、自动捆扎机、装箱机器人、码垛机器人等。这些设备协同工作,形成一条高效运转的生产线,从开箱到装箱,再到码垛,每…...
华为OD机考算法题:计算最大乘积
题目部分 题目计算最大乘积难度易题目说明给定一个元素类型为小写字符串的数组,请计算两个没有相同字符的元素长度乘积的最大值。 如果没有符合条件的两个元素,返回 0。输入描述输入为一个半角逗号分隔的小写字符串的数组,2< 数组长度<…...
用友 GRP-U8 存在sql注入漏洞复现
0x01 漏洞介绍 用友 GRP-U8 license_check.jsp 存在sql注入,攻击者可利用该漏洞执行任意SQL语句,如查询数据、下载数据、写入webshell、执行系统命令以及绕过登录限制等。 fofa:app”用友-GRP-U8” 0x02 POC: /u8qx/license_check.jsp?kj…...
vue页面el-tab控件标签栏加入按钮功能
vue页面el-tab控件标签栏加入按钮功能 显示效果为: <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,ref和reactive,用于创建响应式对象。这两个方法都位于Vue.prototype上,因此可以在组件实例中直接使用。 ref ref函数用于创建一个响应式引用对象。这个函数可以接受一个普通的变量或对象作为参数,并返回…...
7 款用于解锁iPhone密码的苹果解锁软件
无法访问您的 iPhone 一定是最烦人的情况之一。 即使您以前从未遇到过这种情况,做好准备总是一个好主意,而不是在它发生时感到无助。事实上,这种情况经常发生并且可能有很多实例,例如忘记密码或购买锁定的二手 iPhone。 牢记 Ap…...
.jnlp
首先配置电脑的java环境。 百度搜索jre下载,会有很多结果,一般选择官网进行下载。 下载正确的jre版本。 我的电脑是windows 64位,根据你自己电脑的情况选择版本进行下载。不懂自己电脑是多少位的可以看下一步。 查看电脑是64位还是32…...
Linux启动之uboot分析
Linux启动之uboot分析 uboot是什么?一、补充存储器概念1.存储器种类1.norflash - 是非易失性存储器(也就是掉电保存)2.nandflash - 是非易失性存储器(也就是掉电保存)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,但不限于元素 element-plus 组件。在完…...
windows应用软件扫描报告 不告谱 要钱
chatGPT开路,帮找。 当你想要查找Windows软件的漏洞而不涉及查看源代码时,你可以使用一些专门设计用于扫描漏洞的工具。这些工具通常会检查已安装的软件和操作系统的漏洞,并提供建议或修补程序。以下是一些可以用于查找Windows软件漏洞的工具…...
世界前沿技术发展报告2023《世界航空技术发展报告》(七)机载系统与武器技术
(七)机载系统与武器技术 1.机载系统技术1.1 美国推进商用5G技术在航空装备中的应用1.2 人工智能技术在航空中的应用日益增多1.3 美国空军研究实验室推出综合座舱感知技术1.4 美国空军为固定翼飞机驾驶员选定新一代头盔1.5 美国DARPA探索通过机载光能量中…...
JAVA 学习笔记——抽象类
概念: 当定义一个类时,常常需要定义一些成员方法来描述类的行为特征,但有时这些方法的实现方式是无法确定的。 例如,前面在定义 Animal 类时,walk()方法用于描述动物的行走行为,但是针对不同的动物&#…...
磁盘调度算法之先来先服务(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接口开发与测试
开发完接口,接下来我们需要对我们开发的接口进行测试。接口测试的方法比较多,使用接口工具或者Python来测试都可以,工具方面比如之前我们学习过的Postman或者Jmeter ,Python脚本测试可以使用Requests unittest来测试。 测试思路…...
RK3568-emmc控制器
emmc控制器 eMMC主机控制器具有高度的可配置性和可编程性,并提供高性能的eMMC主机控制器,以AXI作为数据传输的总线接口(主接口),以AHB作为其从接口。 它支持以下功能: - 支持SD-HCI主机版本4模式或更少的 …...
02-操作符及类型转换与控制流程语句
操作符及类型转换与控制流程语句 1.操作符1.1.算数运算符正常的数据运算进行数据运算时,除外,其他运算符可以自动将字符串数字隐形转成数字 1.2.一元运算符JavaScript中有8种常用的一元运算符 (正号)1.的第一种用法:进行数据相加2.放在数据的前面&#…...
判断一个字符串中是否包含中文字符
下面我将为你提供三种常用的方法: 方法一:使用正则表达式 import java.util.regex.Pattern; import java.util.regex.Matcher;public class ChineseCharacterChecker {public static boolean containsChineseCharacters(String input) {String regex …...
软件测试面试怎样介绍自己的测试项目?会问到什么程度?
想知道面试时该怎样介绍测试项目?会问到什么程度?那就需要换位思考,思考HR在这个环节想知道什么。 HR在该环节普遍想获得的情报主要是下面这2个方面: 1)应聘者的具体经验和技术能力, 2)应聘者的…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
