JavaScript双向链表实现LRU缓存算法的示例代码

yizhihongxing

首先,我们需要了解下什么是双向链表和LRU缓存算法。

双向链表:每个节点有两个指针,一个指向其前驱节点,一个指向其后继节点。双向链表的优势在于可以快速对链表中的任意节点进行插入、删除和移动操作,时间复杂度均为O(1)。

LRU缓存算法:Least Recently Used,即最近最少使用。LRU缓存算法通过记录缓存中每个数据项的访问时间,当缓存空间满时,将最近最少使用的数据项从缓存中移除,以空出空间保存新数据。

接下来是双向链表实现LRU缓存算法的示例代码:

class CacheNode {
  constructor(key, value) {
    this.key = key
    this.value = value
    this.prev = null
    this.next = null
  }
}

class LRUCache {
  constructor(capacity) {
    this.capacity = capacity
    this.length = 0
    this.head = new CacheNode(null, null)
    this.tail = new CacheNode(null, null)
    this.head.next = this.tail
    this.tail.prev = this.head
    this.cache = {}
  }

  get(key) {
    if (key in this.cache) {
      const node = this.cache[key]
      this.moveToHead(node)
      return node.value
    } else {
      return -1
    }
  }

  put(key, value) {
    if (key in this.cache) {
      const node = this.cache[key]
      node.value = value
      this.moveToHead(node)
    } else {
      const node = new CacheNode(key, value)
      this.cache[key] = node
      this.addToHead(node)
      this.length++
      if (this.length > this.capacity) {
        this.removeTail()
        this.length--
      }
    }
  }

  moveToHead(node) {
    this.removeNode(node)
    this.addToHead(node)
  }

  addToHead(node) {
    node.prev = this.head
    node.next = this.head.next
    this.head.next.prev = node
    this.head.next = node
  }

  removeNode(node) {
    node.prev.next = node.next
    node.next.prev = node.prev
  }

  removeTail() {
    const node = this.tail.prev
    this.removeNode(node)
    delete this.cache[node.key]
  }
}

这里我们定义了两个类:CacheNode 和 LRUCache。CacheNode 表示缓存的节点,包含一个key和value属性,以及两个指针prev和next。LRUCache 是缓存的数据结构,包含一个capacity属性表示缓存容量,一个length属性表示当前缓存中元素的数量,一个head属性表示双向链表的头节点,一个tail属性表示双向链表的尾节点,和一个cache对象表示缓存中的所有数据。

get(key) 方法表示获取缓存中的数据。如果不存在,则返回-1。如果存在,则将对应节点移动到双向链表的头部,表示最近使用了该数据,并返回节点的值。

put(key, value) 方法表示往缓存中添加数据。如果缓存中已经存在该数据,直接移动到双向链表的头部即可。如果不存在,新建一个节点,添加到双向链表的头部,并在cache中增加对key的引用。如果缓存容量已满,需要将双向链表尾部的节点删掉,并在cache中删除对应的key的引用。

moveToHead(node) 方法表示将节点移动到双向链表的头部,表示最近使用了该数据。需要先将该节点从双向链表中删除,然后添加到双向链表的头部。

addToHead(node) 方法表示添加节点到双向链表的头部。

removeNode(node) 方法表示从双向链表中删除节点。

removeTail() 方法表示删除双向链表的尾节点。需要先删除该节点的引用,再从双向链表中删除该节点。

下面是一个示例:

const cache = new LRUCache(2)

cache.put(1, 'a')
cache.put(2, 'b')

console.log(cache.get(1)) // output: 'a'

cache.put(3, 'c')

console.log(cache.get(2)) // output: -1

cache.put(4, 'd')

console.log(cache.get(1)) // output: -1
console.log(cache.get(3)) // output: 'c'
console.log(cache.get(4)) // output: 'd'

这里我们创建了一个容量为2的LRUCache。然后分别往cache中添加数据,最后输出各个数据的值。在输出数据之前,我们先打印LRUCache的状态。可以看到,当调用put方法,向cache中添加第3个元素时,cache中已经满了,需要将最旧的数据(key=1)删除。最后输出的结果中也验证了这点。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript双向链表实现LRU缓存算法的示例代码 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • node.js中RPC(远程过程调用)的实现原理介绍

    下面是详细讲解“node.js中RPC(远程过程调用)的实现原理介绍”的完整攻略。 什么是RPC RPC(Remote Procedure Call)即远程过程调用,是一种计算机通信协议。它允许程序调用其他进程或者跨网络机器上的线程上的函数,而不需要程序员显式编写网络通信代码。 在RPC中,客户机调用服务器上的远程过程,就像本地调用一样。RPC框架会自动将数…

    node js 2023年6月8日
    00
  • 基于NodeJS开发钉钉回调接口实现AES-CBC加解密

    下面是关于基于NodeJS开发钉钉回调接口实现AES-CBC加解密的完整攻略。 简介 钉钉回调接口是钉钉提供的一种主动通知机制,允许开发者注册特定类型的事件(比如用户离职、群组变化等),当事件发生时,钉钉会向开发者指定的服务器推送消息,以便开发者及时获取钉钉中发生的各种变化情况。 为保证安全性,钉钉回调接口推送的消息采用了AES-CBC加密方式,需要在服务器…

    node js 2023年6月8日
    00
  • nodejs导出excel的方法

    下面是“Node.js导出Excel的方法”的完整攻略: 1. 安装依赖包 在Node.js中,我们可以使用exceljs模块来实现导出Excel文件的功能。因此,需要先使用npm安装该模块: npm install exceljs –save 2. 创建Excel文件并添加数据 安装完成后,我们可以在代码中引入该模块,创建一个Workbook对象,然后在…

    node js 2023年6月8日
    00
  • node.js使用Moment.js js 时间计算方法示例小结

    Node.js是一种基于Chrome V8 JavaScript引擎构建的JavaScript运行时工具,它使得JavaScript能够在服务器端运行,同时还支持NPM(Node Package Manager)模块化开发,这为Node.js带来了强大的扩展能力。而Moment.js是一种用于解析、格式化和操作日期对象的JavaScript库,它易于使用且具…

    node js 2023年6月8日
    00
  • koa+mongoose实现简单增删改查接口的示例代码

    我来给你讲解一下 “koa+mongoose实现简单增删改查接口的示例代码”的完整攻略。 一、前期准备 在开始编写代码之前,我们需要先准备一些工作: 安装koa和koa-router npm install koa koa-router –save 安装mongoose npm install mongoose –save 创建并连接数据库 在进行增删改…

    node js 2023年6月8日
    00
  • D3.js 实现带伸缩时间轴拓扑图的示例代码

    下面是“D3.js 实现带伸缩时间轴拓扑图的示例代码”的完整攻略。 1.介绍 D3.js是一个数据驱动的JavaScript库,非常适合用于动态生成交互式数据可视化。在这篇攻略中,我们将学习如何使用D3.js创建带有伸缩时间轴的拓扑图。 2.准备工作 在开始创建拓扑图之前,您需要以下几个工具: 最新版本的D3.js HTML、CSS和JavaScript编辑…

    node js 2023年6月8日
    00
  • js DOM模型操作

    什么是DOM模型? DOM代表“文档对象模型”,它是一种访问和操作HTML和XML文档的标准方法。通过DOM,开发者可以使用JavaScript以及其他编程语言来处理HTML和XML文档的内容、结构以及样式。 在浏览器中,所有的HTML和XML文档都会被转换成一个树形结构的文档对象模型。每个节点都代表了文档中的一个元素、属性、文本或者其他内容。 获取DOM节…

    node js 2023年6月8日
    00
  • Node快速切换版本、版本回退(降级)、版本更新(升级)

    Node.js是一个非常流行的JavaScript运行时环境。由于Node.js的版本更新速度非常快,因此有时我们需要快速切换版本、降级或升级版本。以下是Node.js版本管理的完整攻略: 1. 使用nvm管理Node.js版本 nvm是Node.js版本管理器,它可以方便地在多个版本之间切换。安装nvm后,可以通过以下步骤来快速切换Node.js版本: 1…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部