LRU(least recent used)算法,指的是最近最少访问淘汰算法,是内存不够的场景下,淘汰旧内容的策略。当内存中发生缺页异常的时候,需要从磁盘中读出最新的一页,那原来的一段时间内最少被访问的那一页就需要被替换掉。如何自己实现一个LRU队列,给定队列的容量,使之在常数时间内就能实现插入新的一页,删除最少访问的一页等操作呢?

我们用基于hashmap和双向链表的方法:

如上图所示:head和tail表示双向链表的头和尾部,LRU队列就是头尾之间的双向链表。我们定义了一个hash表,存放不同的key值对应的链表节点的地址。这样通过key就可以以常数的时间来访问到链表头,找到有没有这个节点了。如果hashmap里面的容量少于标定容量,在访问时,首先寻找存不存在当前节点,如果存在就只是修改值,不存在则插入,注意之后需要把这个节点放在队首表示最近访问;如果已经超出容量了,可以先插入,然后在删除尾结点(最近最少访问到)。

java代码如下:

class DLinkedNode {String key;int value;DLinkedNode pre;DLinkedNode post;
}
public class LRUCache {private Hashtable<Integer, DLinkedNode>cache = new Hashtable<Integer, DLinkedNode>();private int count;private int capacity;private DLinkedNode head, tail;public LRUCache(int capacity) {this.count = 0;this.capacity = capacity;head = new DLinkedNode();head.pre = null;tail = new DLinkedNode();tail.post = null;head.post = tail;tail.pre = head;}public int get(String key) {DLinkedNode node = cache.get(key);if(node == null){return -1; // should raise exception here.}// move the accessed node to the head;this.moveToHead(node);return node.value;}public void set(String key, int value) {DLinkedNode node = cache.get(key);if(node == null){DLinkedNode newNode = new DLinkedNode();newNode.key = key;newNode.value = value;this.cache.put(key, newNode);this.addNode(newNode);++count;if(count > capacity){// pop the tailDLinkedNode tail = this.popTail();this.cache.remove(tail.key);--count;}}else{// update the value.node.value = value;this.moveToHead(node);}}/*** Always add the new node right after head;*/private void addNode(DLinkedNode node){node.pre = head;node.post = head.post;head.post.pre = node;head.post = node;}/*** Remove an existing node from the linked list.*/private void removeNode(DLinkedNode node){DLinkedNode pre = node.pre;DLinkedNode post = node.post;pre.post = post;post.pre = pre;}/*** Move certain node in between to the head.*/private void moveToHead(DLinkedNode node){this.removeNode(node);this.addNode(node);}// pop the current tail.private DLinkedNode popTail(){DLinkedNode res = tail.pre;this.removeNode(res);return res;}
}

比如一个限定容量为3的LRU,进行下面的操作,示意图如下:

save("key1", 7)

save("key2", 0)

save("key3", 1)

save("key4", 2)

get("key2")

save("key5", 3)

get("key2")

save("key6", 4)

相应的 LRU 双向链表部分变化如下:

缓存淘汰算法 LRU相关推荐

  1. mysql缓存淘汰机制_聊聊缓存淘汰算法-LRU 实现原理

    前言 我们常用缓存提升数据查询速度,由于缓存容量有限,当缓存容量到达上限,就需要删除部分数据挪出空间,这样新数据才可以添加进来.缓存数据不能随机删除,一般情况下我们需要根据某种算法删除缓存数据.常用淘 ...

  2. 缓存淘汰算法--LRU算法

    缓存淘汰算法--LRU算法 参考: https://www.cnblogs.com/dailidong/p/7571178.html https://blog.csdn.net/wangxilong1 ...

  3. 缓存淘汰算法——LRU算法详细总结及代码实现

    什么是LRU算法? LRU是一种缓存淘汰策略,对于我们的计算机来说,缓存容量是有限的,那么当缓存满了要怎么办?这时就要用到LRU,对于很久没有用过的数据,我们可以将其判定为无用的数据,当新资源进入缓存 ...

  4. 看动画轻松理解「链表」实现「LRU缓存淘汰算法」

    作者 | 程序员小吴,哈工大学渣,目前正在学算法,开源项目 「 LeetCodeAnimation 」5500star,GitHub Trending 榜连续一月第一. 本文为 AI科技大本营投稿文章 ...

  5. 看动画理解「链表」实现LRU缓存淘汰算法

    前几节学习了「链表」.「时间与空间复杂度」的概念,本节将结合「循环链表」.「双向链表」与 「用空间换时间的设计思想」来设计一个很有意思的缓存淘汰策略:LRU缓存淘汰算法. 循环链表的概念 如上图所示: ...

  6. 算法必知 --- LRU缓存淘汰算法

    作者:_code_x 链接:https://www.jianshu.com/p/b7fed77324b9 写在前 就是一种缓存淘汰策略. 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾 ...

  7. 数据结构与算法 / LRU 缓存淘汰算法

    一.诞生原因 缓存是一种提供数据读取性能的技术,在硬件设计.软件开发中有广泛的应用,比如常见的 CPU 缓存,DB 缓存和浏览器缓存等.但是缓存的大小是有限的,需要一定的机制判断哪些数据需要淘汰,即: ...

  8. 06 | 链表(上):如何实现LRU缓存淘汰算法?

    缓存 作用 缓存是一种提高数据读取性能的技术,在硬件设计.软件开发中都有着非常广泛的应用,比如常见的 CPU 缓存.数据库缓存.浏览器缓存等等. 淘汰策略 常见的策略有三种:先进先出策略 FIFO(F ...

  9. leetcode刷题:LRU缓存淘汰算法

    题目: 分析: 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置.但问题是,删除哪些内容呢?我们肯定希望删掉哪些没什么用的缓存,而把有用的数据继续留在缓存里,方便之后继续使用.那么, ...

最新文章

  1. luogu P4085 [USACO17DEC]Haybale Feast(尺取法 + 线段树)
  2. MySQL性能优化的21条最佳经验
  3. 关于联通短信发送程序(SGIP协议)没有收到返回状态报告的报告(使用WireShark分析)
  4. php如何清理网站缓存,php怎么清除opcache缓存
  5. datatables.js 简单使用--多选框和服务器端分页
  6. DTW动态时间规整算法
  7. redis源码分析 ppt_【Redis】redis各类型数据结构和底层实现源码分析
  8. -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -webkit-font-smoothing: antialiased
  9. 基于SSM+SpringBoot+MySQL的社区管理系统
  10. dns缓存时间 linux,如何在Linux服务器上刷新DNS缓存
  11. xml:使用xmlspy创建xml文件,且通过xml文件生成对应的dtd文件
  12. 台电幻彩(t4jn)系列u盘量产修复工具
  13. 阿里云国际站代充值个人注册与分销商邀约区别
  14. fieldtrip学习——1.坐标系介绍(ctf坐标系和acpc坐标系简介)
  15. 群晖域名解析 DDNS ——阿里云 DNS 脚本
  16. [NLP --- 3] 文档检索算法TF-IDF
  17. SpringBoot学习笔记(六)——Redis数据库
  18. 单页面cnd 引入 vant+vue+h5 应用vant
  19. 话费充值API接口源码文档
  20. java驱动打印机_本地打印机驱动程序如何找到网络打印机?

热门文章

  1. python教程pdf-python基础教程[高清][中文第2版].pdf
  2. python和c++哪个好-升学为主的编程学python和C++哪个好?
  3. check mk mysql_Mysql管理必备工具Maatkit详解之四(mk-duplicate-key-checker)
  4. 用c++实现简单单链表,双链表,二叉树类
  5. 文档权限服务器上,服务器上的权限
  6. c语言int grade 5,C语言补考!!!
  7. 指针法算中点坐标c语言,C语言:利用指针编写程序,用梯形法计算给定的定积分实例...
  8. delphi基于html页面和xml实现表单填写,如何从xml文件读取数据,并以delphi语言显示在文本框中...
  9. EasyUI的combobox
  10. 软考高级报考,科目思维导图概览和介绍