LRU缓存机制(链表实现)

简介: LRU缓存机制(链表实现)

题目描述

image.png

解题思路

  1. 构造一个链表节点类和一个LRU缓存类。
  2. 一个链表的节点应该具有key,value,和next指针和prev指针。
  3. 一个LRU的实例应该具有容量capacity,hash对象,表示这个LRU中节点的数量值的count,两个辅助链表节点,分别指向最近使用的元素,和最久未使用的元素。
  4. get方法:无论是get方法还是put方法,都要首先取出key对应的节点,判断这个节点是否是undefined,如果不存在,直接返回-1,如果存在,将其从链表中删除,然后添加到辅助链表Head的指向位置,然后返回该节点的值。
  5. put方法:首先取出key对应的节点,判断这个节点是否是undefined,如果不是undefiend,更新其值,然后从链表中删除,然后添加到辅助头节点指向的位置,如果不存在,首先判断LRU中节点的数量和容量是否相等,如果相等,则说明已经满了,此时从尾部辅助链表前取出该元素,然后删除链表中的该元素,然后从hash对象中也删除,同时count--,然后创造一个新节点,存入key,value,然后添加到链表和hash对象中,同时更新count的值。

AC代码

// 首先构造一个链表节点类
class ListNode {
  constructor(key,value) {
    this.key = key;
    this.value = value;
    this.next = null;
    this.prev = null;
  }
}
// 构造一个LRU缓存类
class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.hash = {};
    this.count = 0;
    // 这里的head可以理解为最近使用过的,tail则可以理解为最久未使用的
    this.dummyHead = new ListNode();
    this.dummyTail = new ListNode();
    this.dummyHead.next = this.dummyTail;
    this.dummyTail.prev = this.dummyHead;
  }
  // 实现get方法
  get(key) {
    // 首先取出hash对象中这个键对应的节点
    let node = this.hash[key];
    // 如果这个节点不存在,返回-1
    if (node === undefined) return -1;
    // 如果这个节点存在的话,从链表中移除已有节点,然后再添加到头部
    this.deleteFromList(node);
    this.addToHead(node);
    return node.value;
  }
  // 实现put方法
  put(key,value) {
    // 首先取出哈希对象中这个键对应的节点
    let node = this.hash[key];
    // 分存在和不存在两种情况进行讨论
    if (node === undefined) {
      // 如果LRU是满的
      if (this.count === this.capacity) {
        // 取出最久未使用的
        let tail = this.dummyTail.prev;
        // 从LRU中删除
        this.deleteFromList(tail);
        // 从hash对象中删除
        delete this.hash[tail.key];
        // LRU的数量-1
        this.count--;
      }
      // 创造一个新的节点
      let newNode = new ListNode(key,value);
      this.hash[key] = newNode;
      this.addToHead(newNode);
      this.count++;
    } else {
      // 更新value
      node.value = value;
      this.deleteFromList(node);
      this.addToHead(node);
    }
  }
  deleteFromList(node) {
    let temp1 = node.prev;
    let temp2 = node.next;
    temp1.next = temp2;
    temp2.prev = temp1;
  }
  addToHead(node) {
    node.prev = this.dummyHead;
    node.next = this.dummyHead.next;
    this.dummyHead.next.prev = node;
    this.dummyHead.next = node;
  }
}
复制代码

题目反思

关于LRU缓存机制这个题目,我们可以采用Map做,也可以采用hash对象+链表的形式做,但是从题目简洁的程度看,Map的方法更加易懂,更加简洁。

相关文章
|
24天前
|
缓存 算法 数据挖掘
深入理解缓存更新策略:从LRU到LFU
【10月更文挑战第7天】 在本文中,我们将探讨计算机系统中缓存机制的核心——缓存更新策略。缓存是提高数据检索速度的关键技术之一,无论是在硬件还是软件层面都扮演着重要角色。我们会详细介绍最常用的两种缓存算法:最近最少使用(LRU)和最少使用频率(LFU),并讨论它们的优缺点及适用场景。通过对比分析,旨在帮助读者更好地理解如何选择和实现适合自己需求的缓存策略,从而优化系统性能。
40 3
|
2月前
|
缓存 Java 数据库连接
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
文章介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的配置和使用,以及如何整合第三方缓存EHCache。详细解释了一级缓存的生命周期、二级缓存的开启条件和配置属性,以及如何通过ehcache.xml配置文件和logback.xml日志配置文件来实现EHCache的整合。
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
|
29天前
|
存储 缓存 负载均衡
Nginx代理缓存机制
【10月更文挑战第2天】
58 4
|
27天前
|
缓存 分布式计算 NoSQL
大数据-47 Redis 缓存过期 淘汰删除策略 LRU LFU 基础概念
大数据-47 Redis 缓存过期 淘汰删除策略 LRU LFU 基础概念
58 2
|
1月前
|
存储 缓存 NoSQL
深入理解后端缓存机制的重要性与实践
本文将探讨在后端开发中缓存机制的应用及其重要性。缓存,作为提高系统性能和用户体验的关键技术,对于后端开发来说至关重要。通过减少数据库访问次数和缩短响应时间,缓存可以显著提升应用程序的性能。本文将从缓存的基本概念入手,介绍常见的缓存策略和实现方式,并通过实例展示如何在后端开发中有效应用缓存技术。最后,我们将讨论缓存带来的一些挑战及其解决方案,帮助您在实际项目中更好地利用缓存机制。
|
2月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
64 8
|
2月前
|
缓存 Java Python
python垃圾回收&缓存机制
python垃圾回收&缓存机制
|
2月前
|
数据安全/隐私保护
基于DAMON的LRU链表排序 【ChatGPT】
基于DAMON的LRU链表排序 【ChatGPT】
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)