LRU算法

LRU算法

LRU算法即最近最少使用算法(Least Recently Used),是一种常用的缓存淘汰策略。其基本思想是,如果一个数据在最近一段时间内没有被访问到,那么它在未来也不太可能被访问到,因此可以将其从缓存中淘汰掉。

LRU算法的实现通常采用哈希表辅以双向链表来完成。具体来说,哈希表用于快速定位缓存中的元素,而双向链表则用于维护缓存中元素的访问顺序。当需要淘汰缓存中的元素时,我们只需要将双向链表尾部的节点删除即可。

LRU算法的例子

以下是一个简单的Java实现LRU算法的例子:

import java.util.*;

public class LRUCache<K, V> {
    private Map<K, Node> map;
    private int capacity;
    private Node head;
    private Node tail;

    private class Node {
        K key;
        V value;
        Node prev;
        Node next;

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

    public LRUCache(int capacity) {
        this.capacity = capacity;
        map = new HashMap<>(capacity);
        head = new Node(null, null);
        tail = new Node(null, null);
        head.next = tail;
        tail.prev = head;
    }

    public V get(K key) {
        Node node = map.get(key);
        if (node == null) {
            return null;
        }
        moveToHead(node);
        return node.value;
    }

    public void put(K key, V value) {
        Node node = map.get(key);
        if (node == null) {
            node = new Node(key, value);
            map.put(key, node);
            addToHead(node);
            if (map.size() > capacity) {
                Node tail = removeTail();
                map.remove(tail.key);
            }
        } else {
            node.value = value;
            moveToHead(node);
        }
    }

    private void addToHead(Node node) {
        node.prev = head;
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
    }

    private void removeNode(Node node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private void moveToHead(Node node) {
        removeNode(node);
        addToHead(node);
    }

    private Node removeTail() {
        Node node = tail.prev;
        removeNode(node);
        return node;
    }
}

LRU算法的具体步骤:

  1. 定义缓存大小和缓存结构:首先需要定义缓存的大小和存储结构。通常使用哈希表加双向链表的结构实现LRU算法。
  2. 查找缓存:当需要查找某个数据时,先在哈希表中查找是否存在该数据。如果存在,则将其移动到双向链表的头部,表示该数据最近被访问过;如果不存在,则说明缓存中没有该数据,需要从磁盘或其他来源加载数据,并插入到双向链表的头部,同时更新哈希表中的映射关系。
  3. 写入缓存:当需要写入数据时,先查找哈希表中是否存在该数据。如果存在,则更新该数据的值,并将其移动到双向链表的头部;如果不存在,则插入到双向链表的头部,并更新哈希表中的映射关系。如果缓存已满,则删除双向链表尾部的数据,同时更新哈希表中的映射关系。

LRU算法的时间复杂度为O(1),因为每次访问或操作都是在哈希表和双向链表中进行,而不需要遍历整个缓存。

代码解释

Java代码实现了LRU缓存算法。以下是每个方法的意图:

  1. 构造函数:初始化LRU缓存的容量,创建一个HashMap用于存储缓存中的数据以及它们在双向链表中的节点,并初始化头结点和尾节点。
  2. get方法:根据key查找缓存中的数据,如果不存在则返回null,否则将对应的节点移动到双向链表的头部,并返回节点的值。
  3. put方法:向缓存中添加数据。如果key已经存在,则更新对应节点的value并将其移到链表头部;如果key不存在,则创建新的节点并将其添加到链表头部,并更新HashMap中的映射关系。如果缓存大小超过限制,则删除双向链表尾部的节点并从HashMap中删除对应的映射关系。
  4. addToHead方法:将节点添加到双向链表头部。
  5. removeNode方法:从双向链表中删除指定节点。
  6. moveToHead方法:将指定节点移动到链表头部。
  7. removeTail方法:删除双向链表尾部的节点,并返回该节点
posted @ 2023-04-01 18:30  进击的小蔡鸟  阅读(39)  评论(0编辑  收藏  举报