操作系统--LRU算法,手撕

今天研究一下LRU算法,上学期学数据结构的时候就应该学一下这个算法,不过后面操作系统也会讲到LRU算法

题目

LRU缓存leetocde146

LRU(Least Recently Used,最近最少使用)算法是一种常见的缓存替换算法,通常用于缓存管理中 。它的核心思想是,当缓存空间满时,会优先淘汰最近最少使用的缓存数据,以便为新的数据腾出空间。LRU算法的基本原理是基于时间局部性原理,即最近被访问的数据很可能在未来会被再次访问。。

如何使用数组或者链表来实现,效率比较对,为了实现On的效率,我们可以采用双链表,但是要找到一个值,双链表的查询还是O(n),那么就可以引入hash,不产生碰撞的情况下,hash的效率是O(1);

所以来用双链表+Hash来实现。

分析;

需要有插入和get操作,并且要求事件复杂度都是O1。

思路 ,对于put操作,如果当前的节点已经存在,修改当前节点的值,再讲节点移动到头节点去。

如果空间已经满了,需要删除最后一个节点,因为是双链表所以事件复杂度为o1,并且将这个节点插入到头部去,再添加进缓存中去。

对于get操作,因为LRU算法遵循的是最近最少使用,每一次使用都会刷新,得到节点的值,并且还需呀将节点的值移动到头部去。

对于moveHead操作,分为两步分为别deleteHead和addHead,都是数据结构双链表之间的操作,插入和删除节点。

java 复制代码
package LRU;


import java.util.HashMap;
import java.util.Map;

public class LRUCache {

    Entry head, tail;
    int capacity;
    int size;
    Map<Integer, Entry> cache;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        size = 0;
        initLinkedList(); //初始化缓存链表
        cache = new HashMap<>(capacity + 2); //引入了两个哨兵
    }

    public void put(int key, int value) {
        Entry node = cache.get(key);
        if (node !=null) {
            node.value = value;
            moveHead(node);
            return;
        }
        if (size == capacity) {
            //空间满了
            Entry lastNode = tail.pre;
            deleteHead(lastNode);
            cache.remove(lastNode.key);
            size--;
        }

        Entry newNode = new Entry();
        newNode.key = key;
        newNode.value = value;
        addNode(newNode);
        cache.put(key, newNode);
        size++;
    }

    public int get(int key) {
        Entry node = cache.get(key);
        if (node ==null) {
            return -1;
        }
        moveHead(node);
        return node.value;
    }

    private void moveHead(Entry node) {
        //删除
        deleteHead(node);
        addNode(node);
    }

    private void addNode(Entry node) {
        //讲节点插入到头节点去
        head.next.pre = node;
        node.next = head.next;
        node.pre = head;
        head.next = node;
    }

    private void deleteHead(Entry node) {
        //双链表删除一个节点
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    public void initLinkedList() {
        head = new Entry();
        tail = new Entry();
        head.next = tail;
        tail.next = head;
    }

    public static class Entry {
        public Entry pre;
        public Entry next;
        public int key;
        public int value;

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

        public Entry() {
        }
    }

    public static void main(String[] args) {
         LRUCache cache=new LRUCache(2);
         cache.put(1,1);
         cache.put(1,2);
        System.out.println(cache.get(1)); //得到现在的缓存2,并且当前的2已经移动到最前面去了
        //再加进来3的时候,1就会被删除
        cache.put(3,3);
        System.out.println(cache.get(2));
    }
}
相关推荐
Mr_Xuhhh几秒前
深入理解单链表的递归反转:从原理到实现
算法·leetcode·职场和发展
智者知已应修善业5 分钟前
【51单片机数码管+蜂鸣器的使用】2023-6-14
c++·经验分享·笔记·算法·51单片机
艾莉丝努力练剑8 分钟前
【Linux线程】Linux系统多线程(七):<线程同步与互斥>线程同步(下)
java·linux·运维·服务器·c++·学习·操作系统
迷途之人不知返12 分钟前
算法类型:双指针类型
算法
吴可可12316 分钟前
三点绘圆弧的几何实现
算法
kyle~20 分钟前
导航---LIO(激光雷达-惯性里程计)算法
c++·算法·机器人·ros2·导航
AGI前沿28 分钟前
# 反内卷,回基础:Nano-Memory用极简检索与剪枝,解决大模型长对话遗忘
算法·机器学习
无限进步_35 分钟前
【C++】私有虚函数与多态:访问权限不影响动态绑定
开发语言·c++·ide·windows·git·算法·visual studio
君鼎39 分钟前
C++20 新特性全面总结
算法·c++20
枫叶机关录1 小时前
算法笔记:K-means、K-means++与K-Medoids聚类算法--详解、案例分析
算法·聚类·k-means