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

首先,我们需要了解下什么是双向链表和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日

相关文章

  • Angular8升级至Angular13遇到的问题解决

    以下是“Angular8升级至Angular13遇到的问题解决”的完整攻略。 背景 Angular是目前应用非常广泛的前端MVC框架之一。由于Angular版本更新较快,升级过程中会涉及到一定的风险,因此在升级之前需要仔细阅读相关的文档,避免不必要的麻烦。 升级步骤 步骤一:备份项目和依赖 在升级之前,需要备份项目和依赖。稍有不慎就会导致大量的工作和时间被浪…

    node js 2023年6月9日
    00
  • Node.Js生成比特币地址代码解析

    Node.Js生成比特币地址代码解析 本文为大家介绍一种使用Node.Js生成比特币地址的方法,主要是通过调用第三方库来实现。具体步骤如下: 步骤1:安装Node.Js 如果您的电脑尚未安装Node.Js,建议您先去官网下载并安装最新版本。 步骤2:安装比特币相关库 在Node.Js中生成比特币地址,首先需要安装相关的比特币库。可以使用npm命令,安装以下库…

    node js 2023年6月8日
    00
  • 中高级前端必须了解的JS中的内存管理(推荐)

    中高级前端必须了解的JS中的内存管理(推荐) 简介 JavaScript使用自动内存管理机制。内存管理是被广泛忽视的一个主题,但它仍然会影响着我们的代码质量和性能。本攻略将深入讨论JavaScript中的内存管理和内存泄漏。 JavaScript中的内存管理 JavaScript使用垃圾收集器来自动管理内存。垃圾收集器会定期检测和收集不再使用的对象,回收它们…

    node js 2023年6月8日
    00
  • nodejs aes 加解密实例

    下面是关于“nodejs aes 加解密实例”的完整攻略。 前言 AES(Advanced Encryption Standard,高级加密标准)是一种可在各种设备上使用的加密算法。在本文中,我们将介绍如何在nodejs中使用AES加解密算法进行数据的加密和解密。 使用crypto模块进行加解密 nodejs中的crypto模块提供了一种简单的方式来加密和解…

    node js 2023年6月8日
    00
  • js AppendChild与insertBefore用法详细对比

    当我们要向HTML页面中增加新的元素节点时,可以使用JS的appendChild和insertBefore方法。两者都可以用于向一个父元素节点中添加一个子元素节点,但有些细节不同。下面是对比它们的用法的详细攻略。 使用appendChild方法 appendChild方法是用于在一个元素节点的子节点列表的末尾添加一个新的子元素节点。其语法如下: parent…

    node js 2023年6月8日
    00
  • 浅析Nodejs npm常用命令

    我将为您详细讲解“浅析Nodejs npm常用命令”的完整攻略。 一、 什么是npm? npm是Node.js的包管理工具,它能够帮助我们安装、管理依赖,以及发布我们自己的包。 二、npm常用命令 1. npm init npm init命令可以让我们创建一个新的package.json文件,这个文件是用来描述我们的项目的,可以在这个文件中设置项目的基本信息…

    node js 2023年6月8日
    00
  • node创建Vue项目步骤详解

    下面是Node创建Vue项目的步骤详解: 准备工作 首先需要安装最新版Node.js和npm; 其次需要安装vue-cli,可以在命令行窗口输入以下命令进行安装: npm install -g vue-cli 创建项目 打开命令行窗口,输入以下命令进行创建项目: vue init webpack my-project 其中,my-project为项目名称,可…

    node js 2023年6月8日
    00
  • nodejs使用async模块同步执行的方法

    使用async模块可以简化Node.js中异步操作时的代码编写,其中包括对异步函数回调的处理、控制函数执行的并发数等操作。 Async提供了很多同步处理方法,本文将详细介绍如何使用async模块同步执行的方法。 安装async模块 在Node.js中使用async模块,需要先进行安装。通过npm命令可以快速安装async模块,命令如下: npm instal…

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