首页 > 其他分享 >Go的数据结构与实现【LRU Cache】

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

时间:2024-04-02 13:00:04浏览次数:18  
标签:node 缓存 Cache list value LRU Value key Go

介绍

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

LRU Cache

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

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

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

实现

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

type K int
type V int

type Cache struct {
	Key   K
	Value V
}

type LRUCache struct {
	size    int
	list    *list.List
	element 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 pair
		value := node.Value.(*list.Element).Value.(Cache).Value
		// move node to the front of list
		c.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 list
		c.list.MoveToFront(node)
		// update key value pair
		node.Value.(*list.Element).Value = Cache{Key: key, Value: value}
	} else {
		// there is no key in LRU cache
		if c.list.Len() == c.size {
			// LRU is full
			lastKey := c.list.Back().Value.(*list.Element).Value.(Cache).Key
			delete(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 = nil
	c.element = nil
}

标签:node,缓存,Cache,list,value,LRU,Value,key,Go
From: https://blog.csdn.net/ldxxxxll/article/details/137265824

相关文章

  • 从零开始构建gRPC的Go服务
    介绍ProtocolBuffersandgRPC是用于定义通过网络有效通信的微服务的流行技术。许多公司在Go中构建gRPC微服务,发布了他们开发的框架,本文将从gRPC入门开始,一步一步构建一个gRPC服务。背景之前在B站看过一个gRPC教学视频,尝试跟着视频做但踩了不少的坑,因此决定自己动手从官......
  • 5.103 BCC工具之filegone.py解读
    一,工具简介filegone 追踪文件消失的原因,无论是被删除还是被重命名。二,代码示例#!/usr/bin/pythonfrom__future__importprint_functionfrombccimportBPFimportargparsefromtimeimportstrftime#argumentsexamples="""examples:./filegone......
  • 一文教你实战构建消息通知系统Django
    本文分享自华为云社区《构建实时消息通知系统:Django实战指南》,作者:柠檬味拥抱。在Web应用程序中,实现消息通知系统是至关重要的,它可以帮助用户及时了解到与其相关的事件或动态。Django提供了信号机制,可以用于实现这样的通知系统。本文将介绍如何使用Django的信号机制来构建一个简......
  • Golang | Leetcode Golang题解之第4题寻找两个正序数组的中位数
    题目:题解:funcfindMedianSortedArrays(nums1[]int,nums2[]int)float64{iflen(nums1)>len(nums2){returnfindMedianSortedArrays(nums2,nums1)}m,n:=len(nums1),len(nums2)left,right:=0,mmedian1,median2:=0,0......
  • golang语言系列:Scrum、Kanban等敏捷管理策略
    云原生学习路线导航页(持续更新中)本文是golang语言系列文章,主要对编程通用技能Scrum、Kanban等敏捷管理策略进行学习1.什么是敏捷开发敏捷是一个描述软件开发方法的术语,它强调增量交付、团队协作、持续规划和持续学习。2001年,敏捷宣言提出:个体和交互胜过流程和......
  • 【Cache】将常用的“小表”缓存到Buffer Cache
    对于那些被经常以全表扫描访问获取数据的“小表”来说,为了提升性能可以考虑将这些表cache在BufferCache中。什么样的表可以称其为“小表”呢?例如经常被访问的参数表,此类表通常包含的数据量并不大,经常以全表扫描的访问形式对其进行访问。如果不强制将这些表cache在BufferCache中,......
  • 每日一题 --- 找出字符串中第一个匹配项的下标[力扣][Go]
    找出字符串中第一个匹配项的下标题目:28.找出字符串中第一个匹配项的下标给你两个字符串haystack和needle,请你在haystack字符串中找出needle字符串的第一个匹配项的下标(下标从0开始)。如果needle不是haystack的一部分,则返回-1。示例1:输入:haystack="sa......
  • 每日一题 --- 右旋字符串[卡码][Go]
    右旋字符串题目:55.右旋字符串(第八期模拟笔试)(kamacoder.com)题目描述字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串s和一个正整数k,请编写一个函数,将字符串中的后面k个字符移到字符串的前面,实现字符串的右旋转操作。例如,对于......
  • 【书籍】Django项目实例精解(第2版) pdf 下载
    Django项目实例精解(第2版)pdf下载作者:安东尼奥·米勒ISBN:9787302526551文件格式:pdf目录第1章构建博客应用程序11.1安装Django11.1.1创建隔离的Python环境21.1.2利用pip安装Django31.2创建第一个项目31.2.1运行开发服务器51.2.2项目设置61.......
  • 【跳频通信】基于Gold码序列跳频通信附Matlab代码
     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。......