Go的数据结构与实现【LRU Cache】

介绍

在本文中,我们将用Go实现LRU Cache。

LRU Cache

最近最少使用(LRU)是一种缓存逐出算法,它按使用顺序组织元素。在LRU中,最长时间没有被使用的元素会被从缓存中逐出。

例如,如果我们有一个容量为三个项目的缓存:
在这里插入图片描述
最初,缓存是空的,我们将元素8放入缓存中,元素9和6像以前一样被缓存。但是现在,缓存容量已满,要放入下一个元素,我们必须驱逐缓存中最近最少使用的元素。
在我们用Go实现LRU缓存之前,最好了解一下缓存的一些方面:

  • 所有操作都应按O(1)的顺序运行
  • 缓存大小有限
  • 所有缓存操作都必须支持并发
  • 如果缓存已满,添加新项必须调用LRU策略

实现

首先定义一些相关数据结构:

type K int
type V inttype Cache struct {Key   KValue V
}type LRUCache struct {size    intlist    *list.Listelement map[K]*list.Element
}

其中含义如下:

  • size:可以存储在缓存中的元素数量
  • list:双向链表,使用Go的原生container/list实现
  • element:映射存储键和指向存储在列表中的值的指针 我们将实现以下的相关方法:
  • Get:获取一个key-value对,如果不存在则返回一个特定值,在这里暂定为-1
  • Put:插入一个key-value对
  • RecentlyUsed:获取最近使用的value
  • Remove:删除一个key-value对
  • Clear:清空缓存

Get

由于缓存将value存储在map中,key-value存储在列表中。首先检查key是否存在于map中,返回存储在双向链表中的key对应的value或返回-1。
在返回值的同时,还需要将它移到双向链表的前面,以保持最近最少使用的逻辑。

func (c *LRUCache) Get(key K) V {if node, ok := c.element[key]; ok {// hit LRU cache, fetch key value pairvalue := node.Value.(*list.Element).Value.(Cache).Value// move node to the front of listc.list.MoveToFront(node)return value}return V(-1)
}

Put
将key-value对插入缓存中遵循以下步骤:

  • 如果在缓存中找到key,则将其移动到双向链表的前面并更新value
  • 否则,检查缓存的当前容量,若溢出,则从双向链表中删除最近最近未使用的条目
  • 将新元素存储在列表的前面。

正如上述步骤所定义的,在检查容量时,我们从缓存中删除了后面的元素,它定义了我们最近最少使用的用例。

func (c *LRUCache) Put(key K, value V) {if node, ok := c.element[key]; ok {// there is already key in LRU cache, move node to the front of listc.list.MoveToFront(node)// update key value pairnode.Value.(*list.Element).Value = Cache{Key: key, Value: value}} else {// there is no key in LRU cacheif c.list.Len() == c.size {// LRU is fulllastKey := c.list.Back().Value.(*list.Element).Value.(Cache).Keydelete(c.element, lastKey)c.list.Remove(c.list.Back())}node := &list.Element{Value: Cache{Key:   key,Value: value,},}pointer := c.list.PushFront(node)c.element[key] = pointer}
}

RecentlyUsed

返回双向链表中最前面的值。

func (c *LRUCache) RecentlyUsed() V {return c.list.Front().Value.(*list.Element).Value.(Cache).Value
}

Remove

删除指定的key,如果key存在于缓存中则删除,否则无操作

func (c *LRUCache) Remove(key K) {if node, ok := c.element[key]; ok {delete(c.element, key)c.list.Remove(node)}
}

Clear

清空缓存,将双向链表和map全部置空

func (c *LRUCache) Clear() {c.list = nilc.element = nil
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/586200.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝牙耳机哪个品牌的好用?五款热销机型推荐,新手入门必备!

​真无线蓝牙耳机近年来非常流行,它们不仅小巧便携,而且在佩戴舒适度和音质方面也逐步超越了有线耳机。面对市场上众多的真无线蓝牙耳机,选择合适的款式可能会令人困惑。我将为你推荐几款既舒适又性能表现不错的蓝牙耳机,希望能帮…

【学习】成为优秀的软件测试工程师需要学哪些知识

成为软件测试工程师,需要学习的内容非常的多,但是无非是这几大类,今天就和小编一起来看看这些知识,你是否都已经掌握。 01、测试环境的搭建 本部分主要是学习从操作系统开始,有关的计算机基础知识、软件和硬件知识、…

【java】关于String、StringBuffer和StringBuilder的那些事

在之前的文章中我们曾简单介绍过String这个引用类型变量,其实它还有许多特性,还有StringBuffer和StringBuilder这两个方法在字符串操作中也有非常重要的地位,接下来就由小编带大家梳理一下吧👊 目录 一、String 1、构造方法 2、…

分库分表 ——12 种分片算法

目录 前言 分片策略 标准分片策略 行表达式分片策略 复合分片策略 Hint分片策略 不分片策略 分片算法 准备工作 自动分片算法 1、MOD 2、HASH_MOD 3、VOLUME_RANGE 4、BOUNDARY_RANGE 5、AUTO_INTERVAL 标准分片算法 6、INLINE 7、INTERVAL COSID 类型算法 …

网络加速器数据可视化大屏:极速网络新体验从这里开始

在信息爆炸的时代,网络已经成为我们日常生活和工作中不可或缺的一部分。然而,网络速度慢、不稳定等问题时常困扰着我们,让许多重要的工作和学习进度受到严重影响。 网络加速器数据可视化大屏集数据分析、可视化展示于一体,它不仅能…

docker--部署 (超详版) (五)

环境准备:docker,mysql,redis,镜像,nginx 把虚拟机打开,连接xshell,参考博客: https://blog.csdn.net/m0_74229802/article/details/136965820?spm1001.2014.3001.5501 一&#x…

GoogLeNet

文章目录 Inception块GoogLeNet模型 Inception块 在GoogLeNet中,基本的卷积块被称为Inception块,如下图所示: Inception块由四条并行路径组成。 前三条路径使用窗口大小为1x1,3x3和 5x5的卷积,从不同空间大小中提取信息。中间的两条路径在输…

SambaNova 芯片:深入解析其架构和高性能秘诀

SambaNova——一家总部位于帕洛阿尔托的公司已经筹集了超过10亿美元的风险投资,不会直接向公司出售芯片。相反,它出售其定制技术堆栈的访问权限,该堆栈具有专门为运行最大的人工智能模型而设计的专有硬件和软件。 最近,SambaNova…

Kubernetes篇(三)— 资源管理

目录 前言资源管理介绍YAML语言介绍资源管理方式命令式对象管理命令式对象配置声明式对象配置 前言 本章节主要介绍yaml语法和kubernetes的资源管理方式 资源管理介绍 在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes。 …

hcia datacom课程学习(5):MAC地址与arp协议

1.MAC地址 1.1 含义与作用 (1)含义: mac地址也称物理地址,是网卡设备在数据链路层的地址,全世界每一块网卡的mac地址都是唯一的,出厂时烧录在网卡上不可更改 (2)作用&#xff1a…

软考 - 系统架构设计师 - 数据流图案例题

阅读以下关于系统数据分析与建模的叙述,在答题纸上回答问题1至问题3。 【说明】 某公司正在研发一套新的库存管理系统。系统中一个关键事件是接收供应商供货。项目组系统分析员小王花了大量时间在仓库观察了整个事件的处理过程,并开发出该过程所执行活动…

Linux shell编程学习笔记45:uname命令-获取Linux系统信息

0 前言 linux 有多个发行版本,不同的版本都有自己的版本号。 如何知道自己使用的Linux的系统信息呢? 使用uname命令、hostnamectl命令,或者通过查看/proc/version文件来了解这些信息。 我们先看看uname命令。 1 uname 命令的功能和格式 …