fifo算法_缓存算法FIFO、LFU、LRU

阅读文本大概需要3分钟。

0x01:FIFO算法

  FIFO(First in First out),先进先出。其实在操作系统的设计理念中很多地方都利用到了先进先出的思想,比如作业调度(先来先服务),为什么这个原则在很多地方都会用到呢?因为这个原则简单、且符合人们的惯性思维,具备公平性,并且实现起来简单,直接使用数据结构中的队列即可实现。

  在FIFO Cache设计中,核心原则就是:如果一个数据最先进入缓存中,则应该最早淘汰掉。也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉。在FIFO Cache中应该支持以下操作;

  get(key):如果Cache中存在该key,则返回对应的value值,否则,返回-1;

  set(key,value):如果Cache中存在该key,则重置value值;如果不存在该key,则将该key插入到到Cache中,若Cache已满,则淘汰最早进入Cache的数据。

  举个例子:假如Cache大小为3,访问数据序列为set(1,1),set(2,2),set(3,3),set(4,4),get(2),set(5,5)

  则Cache中的数据变化为:

  (1,1)                               set(1,1)

  (1,1) (2,2)                       set(2,2)

  (1,1) (2,2) (3,3)               set(3,3)

  (2,2) (3,3) (4,4)               set(4,4)

  (2,2) (3,3) (4,4)               get(2)

  (3,3) (4,4) (5,5)               set(5,5)

   那么利用什么数据结构来实现呢?

  下面提供一种实现思路:

  利用一个双向链表保存数据,当来了新的数据之后便添加到链表末尾,如果Cache存满数据,则把链表头部数据删除,然后把新的数据添加到链表末尾。在访问数据的时候,如果在Cache中存在该数据的话,则返回对应的value值;否则返回-1。如果想提高访问效率,可以利用hashmap来保存每个key在链表中对应的位置。

0x02:LFU算法

  LFU(Least Frequently Used)最近最少使用算法。它是基于“如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小”的思路。

  注意LFU和LRU算法的不同之处,LRU的淘汰规则是基于访问时间,而LFU是基于访问次数的。举个简单的例子:

  假设缓存大小为3,数据访问序列为set(2,2),set(1,1),get(2),get(1),get(2),set(3,3),set(4,4),

  则在set(4,4)时对于LFU算法应该淘汰(3,3),而LRU应该淘汰(1,1)。

  那么LFU Cache应该支持的操作为:

  get(key):如果Cache中存在该key,则返回对应的value值,否则,返回-1;

  set(key,value):如果Cache中存在该key,则重置value值;如果不存在该key,则将该key插入到到Cache中,若Cache已满,则淘汰最少访问的数据。

  为了能够淘汰最少使用的数据,因此LFU算法最简单的一种设计思路就是 利用一个数组存储 数据项,用hashmap存储每个数据项在数组中对应的位置,然后为每个数据项设计一个访问频次,当数据项被命中时,访问频次自增,在淘汰的时候淘汰访问频次最少的数据。这样一来的话,在插入数据和访问数据的时候都能达到O(1)的时间复杂度,在淘汰数据的时候,通过选择算法得到应该淘汰的数据项在数组中的索引,并将该索引位置的内容替换为新来的数据内容即可,这样的话,淘汰数据的操作时间复杂度为O(n)。

  另外还有一种实现思路就是利用 小顶堆+hashmap,小顶堆插入、删除操作都能达到O(logn)时间复杂度,因此效率相比第一种实现方法更加高效。

  如果哪位朋友有更高效的实现方式(比如O(1)时间复杂度),不妨探讨一下,不胜感激。

0x03:LRU算法

LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。

而用什么数据结构来实现LRU算法呢?可能大多数人都会想到:用一个数组来存储数据,给每一个数据项标记一个访问时间戳,每次插入新数据项的时候,先把数组中存在的数据项的时间戳自增,并将新数据项的时间戳置为0并插入到数组中。每次访问数组中的数据项的时候,将被访问的数据项的时间戳置为0。当数组空间已满时,将时间戳最大的数据项淘汰。

  这种实现思路很简单,但是有什么缺陷呢?需要不停地维护数据项的访问时间戳,另外,在插入数据、删除数据以及访问数据时,时间复杂度都是O(n)。

  那么有没有更好的实现办法呢?

  那就是利用链表和hashmap。当需要插入新的数据项的时候,如果新数据项在链表中存在(一般称为命中),则把该节点移到链表头部,如果不存在,则新建一个节点,放到链表头部,若缓存满了,则把链表最后一个节点删除即可。在访问数据的时候,如果数据项在链表中存在,则把该节点移到链表头部,否则返回-1。这样一来在链表尾部的节点就是最近最久未访问的数据项。

  总结一下:根据题目的要求,LRU Cache具备的操作:

  1)set(key,value):如果key在hashmap中存在,则先重置对应的value值,然后获取对应的节点cur,将cur节点从链表删除,并移动到链表的头部;若果key在hashmap不存在,则新建一个节点,并将节点放到链表的头部。当Cache存满的时候,将链表最后一个节点删除即可。

  2)get(key):如果key在hashmap中存在,则把对应的节点放到链表头部,并返回对应的value值;如果不存在,则返回-1。

推荐阅读

Spring Boot 最流行的 16 条实践

SSM框架的面试常见问题

【分布式】缓存穿透、缓存雪崩,缓存击穿解决方案

阿里P7给出的一份超详细 Spring Boot 知识清单

关注我每天进步一点点

aae1da1f8d0ff15c82f42f4c6058b864.png

5636d2ed77c3648864af360f63948b5a.png

你点的每个在看,我都认真当成了喜欢

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

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

相关文章

Pile 0009: Vim命令梳理

正常模式(按Esc或Ctrl[进入) 左下角显示文件名或为空插入模式(按i键进入) 左下角显示--INSERT--可视模式(按v键进入) 左下角显示--VISUAL-- i 在当前位置生前插入 I 在当前行首插入 a 在当前位置后插入 A 在…

Introduction of Version Control/Git, SVN

Introduction of Version Control/Git, SVN 什么是版本控制? 你可以把一个版本控制系统(缩写VCS)理解为一个“数据库”,在需要的时候,它可以帮你完整地保存一个项目的快照。当你需要查看一个之前的快照(称之…

怎样设置计算机远程桌面,电脑如何设置远程连接,手把手教你如何远程

说起远程桌面很多用户都认为是从WIN2000 SERVER才开始引入的,实际上我们可以在WIN98甚至是DOS中看到他的身影。远程桌面采用的是一种类似TELNET的技术,他是从TELNET协议发展而来的。那么如何设置自动开机,下面,我们就来看看如何设…

查看这些有用的ECMAScript 2015(ES6)提示和技巧

by rajaraodv通过rajaraodv 查看这些有用的ECMAScript 2015(ES6)提示和技巧 (Check out these useful ECMAScript 2015 (ES6) tips and tricks) EcmaScript 2015 (aka ES6) has been around for couple of years now, and various new features can be used in clever ways. I…

inputstream转fileinputstream对象_FileInputStream类:文件字节输入流

API ----IO ----字节输入输出流练习 java.lang.Object 继承者 java.io.InputStream 继承者 java.io.FileInputStreampublic FileInputStream类速查速记:直接包装File用于从记事本中读数据 in是针对java来说的,从记事本读入到java* 构造方法:…

IBM将推NVMe存储解决方案

先前,IBM曾对外宣称将开发新的NVMe解决方案,并推动行业参与者进一步探索新协议,以支持更快的数据传输。周日,IBM表示新的语言协议——NVMe(非易失性存储器)正在逐步取代SAS和SATA等旧有的固态硬盘存储标准。…

html5中3个盒子怎样设置,Web前端开发任务驱动式教程(HTML5+CSS3+JavaScript)任务10 盒子模型及应用.pptx...

第五单元 盒子模型任务10 盒子模型及应用学习目标盒子模型的概念掌握边框的设置内边距的设置外边距的设置学习目标了解:利用盒子模型布局网页的优势任务目标实战演练——制作古诗文欣赏网页强化训练——制作散文赏析网页知识准备1. 盒子模型的概念知识准备1. 盒子模型的概念CSS…

SQL手工注入入门级笔记(更新中)

一、字符型注入 针对如下php代码进行注入: $sql"select user_name from users where name$_GET[name]"; 正常访问URL:http://url/xxx.php?nameadmin 此时实际数据库语句: select user_name from users where nameadmin 利用以上结果可想到SQL注入构造语句…

materialize_使用Materialize快速介绍材料设计

materialize什么是材料设计? (What is Material Design?) Material Design is a design language created by Google. According to material.io, Material Design aims to combine:Material Design是Google创建的一种设计语言。 根据material.io ,Mate…

python处理完数据导入数据库_python 将execl测试数据导入数据库操作

import xlrd import pymysql # 打开execl表 book xlrd.open_workbook(XXXX测试用例.xlsx) sheet book.sheet_by_name(Sheet1) # print(sheet.nrows) # 创建mysql连接 conn pymysql.connect( host127.0.0.1, userroot, password123456, dbdemo1, port3306, charsetutf8 ) # 获…

增删改查类

<?php // 所有数据表的基类 abstract class Model {protected $tableName "";protected $pdo "";protected $sql"";function __construct() {$pdo new PDO( "mysql:host" . DB_HOST . ";dbname" . DB_NAME, DB_USERN…

html网页和cgi程序编程,CGI 编程方式学习

1.大家都知道CGI是通用网关接口&#xff0c;可以用来编写动态网页。而且CGI可以用很多种语言来写&#xff0c;用perl来编写最常见&#xff0c;我这里就是用perl来编写做例子。讲到编写CGI编程方式&#xff0c;编写CGI有两程编程风格。(1)功能型编程(function-oriented style)这…

20175305张天钰 《java程序设计》第四周课下测试总结

第四周课下测试总结 错题 某方法在父类的访问权限是public&#xff0c;则子类重写时级别可以是protected。 A .true B .false 正确答案&#xff1a;B 解析&#xff1a;书P122&#xff1a;子类不允许降低方法的访问权限&#xff0c;但可以提高访问权限。 复杂题&#xff08;易错…

强化学习q学习求最值_通过Q学习更深入地学习强化学习

强化学习q学习求最值by Thomas Simonini通过托马斯西蒙尼(Thomas Simonini) 通过Q学习更深入地学习强化学习 (Diving deeper into Reinforcement Learning with Q-Learning) This article is part of Deep Reinforcement Learning Course with Tensorflow ?️. Check the syl…

BZOJ 1113: [Poi2008]海报PLA

1113: [Poi2008]海报PLA Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1025 Solved: 679[Submit][Status][Discuss]Description N个矩形,排成一排. 现在希望用尽量少的矩形海报Cover住它们. Input 第一行给出数字N,代表有N个矩形.N在[1,250000] 下面N行,每行给出矩形的长…

Python自动化运维之常用模块—OS

os模块的作用&#xff1a;  os&#xff0c;语义为操作系统&#xff0c;所以肯定就是操作系统相关的功能了&#xff0c;可以处理文件和目录这些我们日常手动需要做的操作&#xff0c;就比如说&#xff1a;显示当前目录下所有文件/删除某个文件/获取文件大小……  另外&#…

opengl三维图形图形颜色_【图形学基础】基本概念

右手坐标系。类似OpenGL遵循的右手坐标系&#xff1a;首先它是三维的笛卡尔坐标系&#xff1a;原点在屏幕正中&#xff0c;x轴从屏幕左向右&#xff0c;最左是-1&#xff0c;最右是1&#xff1b;y轴从屏幕下向上&#xff0c;最下是-1&#xff0c;最上是1&#xff1b;z轴从屏幕里…

xp职称计算机考试题库,2015年职称计算机考试XP题库.doc

2015年职称计算机考试XP题库.doc (7页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;9.90 积分&#xfeff;2015年职称计算机考试XP题库职称计算机考试考点精编&#xff1a;工具栏的设置与操作XP中将…

Java基础学习-Path环境变量的配置

1.为什么要进行Path环境变量的配置程序的编译和执行需要使用到javac和java命令&#xff0c;所以只能在bin目录下写程序&#xff0c;而实际开发中&#xff0c;我们不可能将程序全部写到bin目录下&#xff0c;所以我们不许让javac和java命令在任意目录下都能够被访问。这时候&…

rails 共享变量_如何将Rails实例变量传递给Vue组件

rails 共享变量by Gareth Fuller由Gareth Fuller 如何将Rails实例变量传递给Vue组件 (How to pass Rails instance variables into Vue components) I’m currently working with a legacy Rails application. We are slowly transitioning the front-end from Rails views to…