golang实现LRU缓存淘汰算法的示例代码

LRU缓存淘汰算法

LRU是最近最少使用策略的缩写,是根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

双向链表实现LRU

将Cache的所有位置都用双链表连接起来,当一个位置被访问(get/put)之后,通过调整链表的指向,将该位置调整到链表头的位置,新加入的Cache直接加到链表头中。

这样,在多次操作后,最近被访问(get/put)的,就会被向链表头方向移动,而没有访问的,向链表后方移动,链表尾则表示最近最少使用的Cache。

当达到缓存容量上限时,链表的最后位置就是最少被访问的Cache,我们只需要删除链表最后的Cache便可继续添加新的Cache。

代码实现

type Node struct {
  Key int
  Value int
  pre *Node
  next *Node
}

type LRUCache struct {
  limit int
  HashMap map[int]*Node
  head *Node
  end *Node
}

func Constructor(capacity int) LRUCache{
  lruCache := LRUCache{limit:capacity}
  lruCache.HashMap = make(map[int]*Node, capacity)
  return lruCache
}

func (l *LRUCache) Get(key int) int {
  if v,ok:= l.HashMap[key];ok {
    l.refreshNode(v)
    return v.Value
  }else {
    return -1
  }
}

func (l *LRUCache) Put(key int, value int) {
  if v,ok := l.HashMap[key];!ok{
    if len(l.HashMap) >= l.limit{
      oldKey := l.removeNode(l.head)
      delete(l.HashMap, oldKey)
    }
    node := Node{Key:key, Value:value}
    l.addNode(&node)
    l.HashMap[key] = &node
  }else {
    v.Value = value
    l.refreshNode(v)
  }
}

func (l *LRUCache) refreshNode(node *Node){
  if node == l.end {
    return
  }
  l.removeNode(node)
  l.addNode(node)
}

func (l *LRUCache) removeNode(node *Node) int{
  if node == l.end {
    l.end = l.end.pre
  }else if node == l.head {
    l.head = l.head.next
  }else {
    node.pre.next = node.next
    node.next.pre = node.pre
  }
  return node.Key
}

func (l *LRUCache) addNode(node *Node){
  if l.end != nil {
    l.end.next = node
    node.pre = l.end
    node.next = nil
  }
  l.end = node
  if l.head == nil {
    l.head = node
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • golang实现LRU缓存淘汰算法的示例代码

    LRU缓存淘汰算法 LRU是最近最少使用策略的缩写,是根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高". 双向链表实现LRU 将Cache的所有位置都用双链表连接起来,当一个位置被访问(get/put)之后,通过调整链表的指向,将该位置调整到链表头的位置,新加入的Cache直接加到链表头中. 这样,在多次操作后,最近被访问(get/put)的,就会被向链表头方向移动,而没有访问的,向链表后方移动,链表尾则表示最近最少使用的Cache

  • 工程师必须了解的LRU缓存淘汰算法以及python实现过程

    大家好,欢迎大家来到算法数据结构专题,今天我们和大家聊一个非常常用的算法,叫做LRU. LRU的英文全称是Least Recently Used,也即最不经常使用.我们看着好像挺迷糊的,其实这个含义要结合缓存一起使用.对于工程而言,缓存是非常非常重要的机制,尤其是在当下的互联网应用环境当中,起到的作用非常重要.为了便于大家更好地理解,我们从缓存的机制开始说起. 缓存 缓存的英文是cache,最早其实指的是用于CPU和主存数据交互的.早年这块存储被称为高速缓存,最近已经听不到这个词了,不知道是不是

  • Java 手写LRU缓存淘汰算法

    概述 LRU 算法全称为 Least Recently Used 是一种常见的页面缓存淘汰算法,当缓存空间达到达到预设空间的情况下会删除那些最久没有被使用的数据 . 常见的页面缓存淘汰算法主要有一下几种: LRU 最近最久未使用 FIFO 先进先出置换算法 类似队列 OPT 最佳置换算法 (理想中存在的) NRU Clock 置换算法 LFU 最少使用置换算法 PBA 页面缓冲算法 LRU 的原理 LRU 算法的设计原理其实就是计算机的 局部性原理(这个 局部性原理 包含了 空间局部性 和 时间

  • java实现LRU缓存淘汰算法的方法

    LRU算法:最近最少使用淘汰算法(Least Recently Used).LRU是淘汰最长时间没有被使用的缓存(即使该缓存被访问的次数最多). 如何实现LRU缓存淘汰算法 场景: 我们现在有这么个真实场景,我在爬取某个网站时,控制该网站的代理IP并发数,太多会搞垮对方网站的对吧,要蹲号子的呢.这里我需要维护一个代理IP代理池,而且这些IP肯定不是一直都很稳定的,但是又不能取一个就丢一个,这样太浪费资源.所以我会将这些IP缓存起来,进行按需提取,采用LRU最近最少使用的策略去管理代理IP. 代码

  • Java实现常用缓存淘汰算法:FIFO、LRU、LFU

    目录 缓存淘汰算法 FIFO LRU LFU 总结 缓存淘汰算法 在高并发.高性能的质量要求不断提高时,我们首先会想到的就是利用缓存予以应对. 第一次请求时把计算好的结果存放在缓存中,下次遇到同样的请求时,把之前保存在缓存中的数据直接拿来使用. 但是,缓存的空间一般都是有限,不可能把所有的结果全部保存下来.那么,当缓存空间全部被占满再有新的数据需要被保存,就要决定删除原来的哪些数据.如何做这样决定需要使用缓存淘汰算法. 常用的缓存淘汰算法有:FIFO.LRU.LFU,下面我们就逐一介绍一下. F

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

    目录 目标 什么是LRU 简介 硬件支持 寄存器 栈 代码实现 思路 链表节点数据结构 链表数据结构 LRUCache数据结构 完整代码 测试 目标 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构. 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 . void put(int key

  • Golang实现常见排序算法的示例代码

    目录 前言 五种基础排序算法对比 1.冒泡排序 2.选择排序 3.插入排序 4.快速排序 前言 现在的面试真的是越来越卷了,算法已经成为了面试过程中必不可少的一个环节,你如果想进稍微好一点的公司,「算法是必不可少的一个环节」.那么如何学习算法呢?很多同学的第一反应肯定是去letcode上刷题,首先我并不反对刷题的方式,但是对于一个没有专门学习过算法的同学来说,刷题大部分是没什么思路的,花一个多小时暴力破解一道题意义也不大,事后看看别人比较好的解法大概率也记不住,所以我觉得「专门针对算法进行一些简

  • Golang实现常见的限流算法的示例代码

    目录 固定窗口 滑动窗口 漏桶算法 令牌桶 滑动日志 总结 限流是项目中经常需要使用到的一种工具,一般用于限制用户的请求的频率,也可以避免瞬间流量过大导致系统崩溃,或者稳定消息处理速率 这个文章主要是使用Go实现常见的限流算法,代码参考了文章面试官:来,年轻人!请手撸5种常见限流算法! 和面试必备:4种经典限流算法讲解如果需要Java实现或更详细的算法介绍可以看这两篇文章 固定窗口 每开启一个新的窗口,在窗口时间大小内,可以通过窗口请求上限个请求. 该算法主要是会存在临界问题,如果流量都集中在两

  • Golang实现AES加密和解密的示例代码

    目录 对称加密 AES 算法 加解密 文件加密解密 说明 对称加密 AES 算法 (Advanced Encryption Standard ,AES) 优点 算法公开.计算量小.加密速度快.加密效率高. 缺点 发送方和接收方必须商定好密钥,然后使双方都能保存好密钥,密钥管理成为双方的负担. 应用场景 相对大一点的数据量或关键数据的加密. 加解密 package helpers import ( "bytes" "crypto/aes" "crypto/c

  • Golang Map实现赋值和扩容的示例代码

    golang map 操作,是map 实现中较复杂的逻辑.因为当赋值时,为了减少hash 冲突链的长度过长问题,会做map 的扩容以及数据的迁移.而map 的扩容以及数据的迁移也是关注的重点. 数据结构 首先,我们需要重新学习下map实现的数据结构: type hmap struct { count int flags uint8 B uint8 noverflow uint16 hash0 uint32 buckets unsafe.Pointer oldbuckets unsafe.Poin

随机推荐