1.背景

LRU(Least Recently Used)是一种常用的缓存淘汰策略,即当缓存满了之后,删除最近最少使用的数据。

LRU的实现,常用的编程语言在语言层面都有实现,可以直接使用。为了深入理解LRU,本文介绍一种通过双链表实现LRU方法。

2.双链表实现方法

Java版双链表实现代码。

2.1 定义节点实体类

/** * 链表节点. * @author liunan1 . */public class Node {  private int key;

  private int value;

  private Node next;

  private Node prev;

  public Node(int key, int value) {    this.key = key;    this.value = value;  }

  public int getKey() {    return key;  }

  public int getValue() {    return value;  }

  public Node getNext() {    return next;  }

  public void setNext(Node next) {    this.next = next;  }

  public Node getPrev() {    return prev;  }

  public void setPrev(Node prev) {    this.prev = prev;  }}

2.2 双链实现类

package lewis.test.algorithm.lru.model;

import java.util.Objects;

/** * 双链表. * @author liunan1 . */public class IntList {  private int length;  private Node head;  private Node tail;

  /**   *  删除最后一个节点.   */  public void removeLast() {    if (Objects.nonNull(tail) && Objects.nonNull(tail.getPrev())) {      Node prev = tail.getPrev();      prev.setNext(null);      tail = prev;      --length;    }  }

  /**   * 查找数据,未找到返回-1.   * @param key   * @return   */  public int get(int key) {    int i = 1;    Node currentNode = head;    for(; i <= length; i++) {      int findKey = currentNode.getKey();      int value = currentNode.getValue();      Node prev = currentNode.getPrev();      Node next = currentNode.getNext();      if (findKey == key) {        // 将节点移动到链表头部        if (Objects.nonNull(prev)) {           // 1.将节点移除           prev.setNext(next);           if (Objects.nonNull(next)) {             next.setPrev(prev);           } else {             // 节点队尾,更新队尾指针.             tail = prev;           }           // 2. 将节点移动到表头           currentNode.setNext(head);           head.setPrev(currentNode);           currentNode.setPrev(null);           head = currentNode;        }        return value;      }      currentNode = next;    }    // 未找到    return -1;  }

  /**   * 头部插入节点.   * @param node node.   */  public void addHead(Node node) {    head.setPrev(node);    node.setNext(head);    head = node;    ++length;  }

  /**   * 链表长度.   * @return 长度.   */  public int size() {     return length;  }}

2.3 LRU模拟实现类

package lewis.test.algorithm.lru.model;

import java.util.Random;

/** * LRU缓存淘汰策略实现类. * @author liunan1 . */public class LeastRecentlyUsedCache {  // 缓存容量  private int capacity;  private IntList list;

  public LeastRecentlyUsedCache(int capacity) {    this.capacity = capacity;  }

  /**   * 从缓存中获取数据.   * @param key .   * @return   */  public int get(int key) {    int value = this.list.get(key);    // 未找到,从磁盘读取.    if (-1 == value) {      // 模拟从磁盘读取.      value = new Random().nextInt(100);      // 插入缓存.      put(key, value);    }    return value;  }

  /**   * 插入数据.   * @param key key.   * @param value value.   */  public void put(int key, int value) {      Node node = new Node(key, value);      list.addHead(node);

      if (list.size() > capacity) {         list.removeLast();      }  }

}

3. 总结与思考

通过三个Java类,模拟实现了LRU,简单明了,易于理解。用心的读取也许已经发现,该实现查找缓存的时候,性能不够好,时间复杂度是O(n)。后续将对该实现进行优化,将时间复杂度提升到O(1)。

广义表head tail 运算_双链表实现LRU缓存淘汰策略相关推荐

  1. 如何基于链表实现 LRU 缓存淘汰算法?

    什么是LRU LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高" ...

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

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

  3. 线性表中的头插法双链表的学习

    #include <stdio.h> #include <malloc.h>/*** 线性表中的头插法双链表的学习 *//*** 人类*/ typedef struct Per ...

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

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

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

    作者 | 吴至波 责编 | 胡巍巍 快速挑战Python全栈工程师: https://edu.csdn.net/topic/python115?utm_source=csdn_bw 前几节学习了「链表 ...

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

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

  7. 考研数据结构——(线性表_双链表)

    双向链表 结构体定义 1. 尾插法初始化双向链表 2. 向后遍历双链表 3. 向前遍历双链表 4. 获取指定位序结点 5. 指定结点后插入结点(目前无法加在第一个位置) 6. 删除指定元素后的元素 ( ...

  8. 单链表删除所有值为x的元素_双链表的基本实现与讲解(C++描述)

    双链表 双链表的意义 单链表相对于顺序表,确实在某些场景下解决了一些重要的问题,例如在需要插入或者删除大量元素的时候,它并不需要像顺序表一样移动很多元素,只需要修改指针的指向就可以了,其时间复杂度为 ...

  9. 双链表java实现_双链表 Java实现数据结构

    创建双链表DoubleLinkedList,带范型 public class DoubleLinkedList { private Node head; private Node tail; priv ...

最新文章

  1. 谷歌翻译大型翻车现场:请服用“反坦克导弹”来缓解疼痛,UCLA:医生们要注意了...
  2. linux Fedora35 grub2 改变启动顺序
  3. 主曲率 matlab,基于Matlab的Hertz接触参数和主曲率差函数关系的拟合
  4. Beautiful Soup的用法
  5. MongoDB内置文档查看和修改
  6. LTE Module User Documentation(翻译5)——Mobility Model with Buildings
  7. Python: pip升级报错了:You are using pip version 10.0.1, however version 20.3.3 is available.
  8. java的地位和优势,Java语言之所以能持续占领霸主地位 这些优势功不可没
  9. 六步带你完成博流wifi模组对接华为云流程
  10. Python 字符串(一)
  11. Android ui 测试课堂笔记
  12. Gstreamer应用g_signal_new/g_signal_connect/g_signal_emit总结(十二)
  13. Python学习笔记010——匿名函数lambda
  14. python爬取网站所有资源
  15. Cramer_rule克莱姆法则讲解
  16. 3d打印人像多少钱?
  17. 高一计算机基础知识题简答题,高一信息技术试题及答案
  18. 经典信息图表:2013 扁平设计 VS 拟物设计
  19. iOS 开发常见崩溃分析
  20. 斐讯设备远程控制教程(以K3、N1为例)

热门文章

  1. [转]微波/毫米波雷达
  2. Spring Boot——开发新一代Spring应用
  3. 2013.11.20 流水
  4. Bailian2795 金银岛【背包+贪心】
  5. Bailian2790 迷宫【DFS】
  6. JSK-27321 统计单词数【字符串】
  7. UVA11582 Colossal Fibonacci Numbers!【快速模幂+数列模除】
  8. Bailian3247 回文素数【素数+回文】(POJ NOI0113-11)
  9. 【繁琐工作自动化】pandas 处理 excel 文件
  10. color2gray 的实现