go设计LRU算法,实现链表和淘汰

go设计LRU算法,实现链表和淘汰

一、LRU算法
LRU(Least Recently Used,最近最少使用)算法是一种常见的页面置换算法,通常用于操作系统内存管理中,也被广泛应用在缓存系统中,如实现一个LRU Cache。该算法的核心思想是基于时间局部性原理:最近被访问的数据很有可能会在不久的将来再次被访问。

  1. 工作原理 :缓存页面置换策略:LRU算法会根据数据的访问顺序来进行置换,如果需要淘汰缓存中的数据,则会将那些最久未被访问的数据移出缓存。
  2. 使用链表记录访问顺序:典型的实现方式是使用双向链表和哈希表。双向链表用于记录数据的访问顺序,靠近头部的节点表示最近被访问的数据,靠近尾部的节点表示最久未被访问的数据;哈希表用于快速检索数据对应的节点。
  3. 数据访问时的处理:当数据被访问时,若数据已经在缓存中,LRU算法会将该数据节点移动到链表头部,表示最近被访问过;若数据不在缓存中,则新数据会被插入链表头部,并检查缓存是否已满,如果缓存已满就淘汰链表尾部数据节点。
  4. 淘汰最久未被访问的数据:当需要淘汰数据时,LRU算法会移除链表尾部节点,最近被访问的数据节点会一直保留在链表头部。

二、源码实现

这个示例代码展示了一个基本的 LRU 缓存实现,使用双向链表(list.List)和哈希表(map)来存储数据。LruCache 结构体包含了一个固定容量的哈希表和双向链表,用于实现 LRU 缓存的基本功能。Get 方法用于获取缓存中的值,Set 方法用于插入或更新缓存,并根据 LRU 算法保持最近访问的元素在链表头部。

在这个示例中,LRU 缓存的容量为 3,当缓存中的元素个数超过容量时,会使用 LRU 策略删除最近最少使用的元素。可以根据实际需求对此基本示例进行扩展和优化。

package main

// 链表
type list struct {
	key   string
	value string
	prev  *list
	next  *list
}

// 存储数据源
type LruCache struct {
	cap   int
	cache map[string]*list
	head  *list
	tail  *list
}

func getLru(cap int) (lru LruCache) {
	var head, tail *list
	head = new(list)
	tail = new(list)
	head.next = tail
	tail.prev = head
	return LruCache{
		cap:   cap,
		cache: make(map[string]*list),
		head:  head,
		tail:  tail,
	}
}

func (t *LruCache) Set(k, v string) {
	if val, ok := t.cache[k]; ok {
		//存在直接更新
		t.cache[k].key = k
		t.cache[k].value = v
		//删除当前位置
		t.remove(val)
		//移到最前面
		t.moveToHead(val)
	} else {
		if len(t.cache) >= t.cap {
			//超如容量需要删除最后一个
			delete(t.cache, t.tail.prev.key)
			t.remove(t.tail.prev)
		}
		newList := &list{key: k, value: v}
		t.cache[k] = newList
		//移到最前面
		t.moveToHead(newList)
	}
}

func (t *LruCache) Get(k string) string {
	if val, ok := t.cache[k]; ok {
		//删除当前位置
		t.remove(val)
		//移到最前面
		t.moveToHead(val)
		return val.value
	}
	return "-1"
}

func (t *LruCache) remove(l *list) {
	//剪短上层联系
	l.prev.next = l.next
	//剪短下层联系
	l.next.prev = l.prev
}

func (t *LruCache) moveToHead(l *list) {
	//移到第一个节点
	l.prev = t.head
	//原有第一个节点改为当前节点的下一个
	l.next = t.head.next
	t.head.next.prev = l
	t.head.next = l
}

func main() {
	cache := getLru(3)
	cache.Set("1", "1")
	cache.Set("2", "2")
	cache.Set("3", "3")
	cache.Set("4", "4")
	cache.Set("5", "5")
	cache.Get("3")
	cache.Get("5")
	cache.Get("2")
}


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HackMyVM-Slowman

目录 信息收集 arp nmap whatweb WEB web信息收集 gobuster FTP匿名登录 hydra mysql爆破 mysql登录 fcrackzip爆破 hashcat爆破 ssh登录 提权 系统信息收集 python Capabilities提权 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interf…

【Java 刷题记录】前缀和

前缀和 25. 一维前缀和 示例1: 输入: 3 2 1 2 4 1 2 2 3输出: 3 6import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public static void main(String[] args) {Scanner in new Scanner(S…

信创 | 信创产业数字化转型与升级:路径规划与实践!

信创产业的数字化转型与升级路径,主要围绕着构建国产化信息技术软硬件底层架构体系和全周期生态体系,解决核心技术关键环节“卡脖子”的问题,以推动中国经济数字化转型的平稳健康发展。 一、信创产业的发展趋势包括: 加强国产信息…

️测试问我:为啥阅读量计数这么简单的功能你都能写出bug?

前言 可乐他们团队最近在做一个文章社区平台,由于人手不够,后端部分也是由前端同学来实现,使用的是 nest 。 今天他接到了一个需求,就是在用户点开文章详情的时候,把阅读量 +1 ,这里不需要判断用户是否阅读过,无脑 +1 就行。 它心想:这么简单,这不是跟 1+1 一样么。…

使用pandas的merge()和join()函数进行数据处理

目录 一、引言 二、pandas的merge()函数 基本用法 实战案例 三、pandas的join()函数 基本用法 实战案例 四、merge()与join()的比较与选择 使用场景: 灵活性: 选择建议: 五、进阶案例与代码 六、总结 一、引言 在数据分析和处理…

领航法律科技,法大大多年深耕再获认可!

近日,“乘势破局 第八届新兴法律服务业高峰论坛”在上海隆重举行。作为国内领先的电子签厂商,法大大凭借在法律科技领域的多年深耕与沉淀,荣获“法律科技领航机构”称号。 据悉,新兴法律服务业高峰论坛作为国内首个聚焦“新兴法律…

董事长张轶群刚被罚,合规问题屡见不鲜,富友支付IPO胜算几何?

第三方支付机构富友支付又双叒来冲刺上市了。 与此前两次冲刺A股不同的是,富友支付此次选择在港股上市。近日,富友支付向港交所主板递交上市申请,联席保荐人为中信证券、申万宏源香港。值得一提的是,此前的2018年、2021年&#x…

网络基础——路由

网络基础——路由 要想网络畅通,应让网络中的路由器知道如何转发数据包到各个网段。路由器根据路由表来转发数据包,而路由表是通过直连网络、静态路由以及动态路由来构建的。 route命令,底层是使用ioctl实现;ip命令,…

Misc 流量分析

流量分析简介 网络流量分析是指捕捉网络中流动的数据包,并通过查看包内部数据以及进行相关的协议、流量分析、统计等来发现网络运行过程中出现的问题。 在CTF比赛中,以及各种技能大赛对于流量包的分析取证是一种十分重要的题型。通常这类题目都是会提供…

Java | Leetcode Java题解之第66题加一

题目&#xff1a; 题解&#xff1a; class Solution {public int[] plusOne(int[] digits) {int n digits.length;for (int i n - 1; i > 0; --i) {if (digits[i] ! 9) {digits[i];for (int j i 1; j < n; j) {digits[j] 0;}return digits;}}// digits 中所有的元素…

【牛客】【模板】差分

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 差分模板。 b[0]a[0]; b[1]a[1]-a[0]; b[2]a[2]-a[1]; ...... b[n-1]a[n-1]-a[n-2]; b[n]a[n]-a[n-1]; 差分标记&#xff1a;b[l]k,b…

2024年荆州中级工程师报名开始了吗?

2024年荆州中级工程师职称报名已经开始了 2024年荆州中级职称报名时间&#xff1a; &#xff08;一&#xff09;网上报名时间&#xff1a; 4月26日9时至5月10日16时。超过时间将不能操作。 &#xff08;二&#xff09;网上缴费时间&#xff1a; 4月26日9时至5月10日24时 网上…

(五)JVM实战——JVM性能调优与监控

JVM调优案例的场景 为什么要调优&#xff1a;防止或者解决jvm虚拟机中的OOM问题&#xff1b;减少FullGC出现的频率&#xff0c;解决系统运行卡、慢问题JVM调优案例的四个方面 OOM(堆溢出)&#xff1a;java heap spaceOOM(元空间溢出)&#xff1a;MetaspaceOOM(GC overhead lim…

分析错误ValueError: could not determine the shape of object type ‘Series‘

这个错误提示 ValueError: could not determine the shape of object type Series 通常发生在尝试将 pandas 的 Series 直接转换为 PyTorch 的 tensor 时&#xff0c;尤其是当 Series 的数据类型不明确或者包含非数值类型的数据时。为了修正这个问题&#xff0c;确保在转换之前…

利用Jenkins完成Android项目打包

问题和思路 目前存在的问题 打包操作由开发人员完成&#xff0c;这样开发进度容易被打断。 解决问题的思路 将打包操作交测试/产品/开发人员来完成&#xff0c;主要是测试/开发。 按照以上的思路&#xff0c;那么JenkinsGradle的解决方案是比较经济的&#xff0c;实现起来…

跟随Facebook的足迹:社交媒体背后的探索之旅

在当今数字化时代&#xff0c;社交媒体已经成为了人们日常生活中不可或缺的一部分。而在这庞大的社交媒体网络中&#xff0c;Facebook作为其中的巨头&#xff0c;一直在引领着潮流。从创立之初的一个大学社交网络到如今的全球性平台&#xff0c;Facebook的发展历程承载了无数故…

雷军-2022.8小米创业思考-6-互联网七字诀之专注:有所为,有所不为;克制贪婪,少就是多;一次解决一个最迫切的需求

第六章 互联网七字诀 专注、极致、口碑、快&#xff0c;这就是我总结的互联网七字诀&#xff0c;也是我对互联网思维的高度概括。 专注 从商业角度看&#xff0c;专注就是要“把鸡蛋尽量放在一个篮子里”。这听起来似乎有些不合理&#xff0c;大家的第一反应可能是“风险会不会…

stripe支付

使用第一个示例 1、示例中的PRICE_ID需要去Stripe控制台->产品目录创建产品 1、 添加产品 2、点击查看创建的产品详情 4、这个API ID就是demo中的PRICE_ID 注意&#xff1a;需要注意的是&#xff0c;测试模式和生产模式中的 $stripeSecretKey 需要对应上。简而言之就是不能生…

【嵌入式必读】一文彻底理解PID自整定及PID自整定代码设计

文章目录 1. 前言2. PID简介3. 常用的PID自整定方法3.1 临界度比例法3.2 衰减曲线法 4. 继电反馈整定法原理4.1 继电反馈自整定的基本思想4.2 继电反馈自整定原理 5. 算法设计5.1 振荡的生成5.2 提取出临界周期 T c T_c Tc​和振荡波形幅值 A A A5.3 计算出PID参数 6 原代码6.1…

【Linux】Docker 安装部署 Nacos

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 【Linux】Docker 安装部署 Nacos docker搜索na…
最新文章