算法:LRU缓存

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

class LRUCache {
  constructor(capacity) {
    this.capacity = capacity  // 容量
    this.hash = {}            // 哈希表
    this.count = 0            // 缓存数目
    this.dummyHead = new ListNode() // 虚拟头结点
    this.dummyTail = new ListNode() // 虚拟尾节点
    this.dummyHead.next = this.dummyTail
    this.dummyTail.prev = this.dummyHead // 还未添加真实节点,将虚拟头尾节点相连
  }
// 哈希表中找不到对应的值,则返回 -1。被读取的节点,要刷新它的位置,移动到链表头部
  get(key) {
    let node = this.hash[key]      // 从哈希表中,获取对应的节点
    if (node == null) return -1    // 如果节点不存在,返回-1
    this.moveToHead(node)          // 被读取了,该节点移动到链表头部
    return node.value              // 返回出节点值
  }

  put(key, value) {
    let node = this.hash[key]            // 获取链表中的node
    if (node == null) {                  // 不存在于链表,是新数据
      if (this.count == this.capacity) { // 容量已满
        this.removeLRUItem()             // 删除最远一次使用的数据
      }
      let newNode = new ListNode(key, value) // 创建新的节点
      this.hash[key] = newNode          // 存入哈希表
      this.addToHead(newNode)           // 将节点添加到链表头部
      this.count++                      // 缓存数目+1
    } else {                   // 已经存在于链表,老数据
      node.value = value       // 更新value
      this.moveToHead(node)    // 将节点移到链表头部
    }
  }

  moveToHead(node) {
    this.removeFromList(node) // 先从链表中删除
    this.addToHead(node) // 再加到链表的头部
  }
  // 先从链表中删除
  removeFromList(node) {
    let temp1 = node.prev// 暂存它的后继节点
    let temp2 = node.next // 暂存它的前驱节点
    temp1.next = temp2 // 前驱节点的next指向后继节点
    temp2.prev = temp1// 后继节点的prev指向前驱节点
  }
  // 插入到虚拟头结点和真实头结点之间
  addToHead(node) {
    node.prev = this.dummyHead// node的prev指针,指向虚拟头结点
    node.next = this.dummyHead.next// node的next指针,指向原来的真实头结点
    this.dummyHead.next.prev = node// 原来的真实头结点的prev,指向node
    this.dummyHead.next = node// 虚拟头结点的next,指向node
  }

  removeLRUItem() {               // 删除“老家伙”
    let tail = this.popTail()     // 将它从链表尾部删除
    delete this.hash[tail.key]    // 哈希表中也将它删除
    this.count--                  // 缓存数目-1
  }

  popTail() {                      // 删除链表尾节点
    let tail = this.dummyTail.prev // 通过虚拟尾节点找到它
    this.removeFromList(tail)      // 删除该真实尾节点
    return tail                    // 返回被删除的节点
  }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值