赞
踩
LRU缓存是一种缓存策略,当缓存满了,需要腾出空间存放新数据时,它会删除最近最少使用的数据。换句话说,它会优先淘汰那些最久没有被访问的元素,以确保缓存中的数据是最近使用的,这对提高缓存系统的命中率有帮助。
假设内存中有5个远端,缓存的大小为 3.
最初缓存是空的,所有元素都存在内存中,我们先访问内存中元素A1,并将其放入缓存中。
接下来,我们访问内存中的元素A2将其放入缓存,A2存储在 最顶端,此时,缓存中的A1下移,因为A1不再是最近访问的元素了。
接下来,我们访问内存中的元素A3,过程与访问A2类似,此时A3位于缓存顶端,A1,A2下移。
现在,我们再次访问A2,我们可以从缓存中获取了,而不是从内存中获取,但是需要注意的是,获取到A2之后,需要将A2移动到缓存的顶部,因为A2是目前最近访问过的元素。
现在,我们访问A4,我们必须从内存中获取它,但是我们将它放到缓存中的哪个位置了,现在缓存已经满了,我们必须删除一些元素以便容纳A4,在本例中,我们删除了最近最少使用的A1,这就是最近最少使用(LRU)算法。
如何设计一个支持以下操作的LRU缓存:
要求:
使用一个固定大小的数组存储缓存中的元素,每个元素除了存储key和value外,还存储一个时间戳timeStamp,标记元素的访问时间。当我们访问或插入一个元素时,更新该元素的时间戳,以表示它是最近使用过的。当缓存满时,我们需要找到时间戳最大的元素(表示最久未使用),将其删除,然后插入新元素。
class DataElement {
int key;
int value;
int timeStamp;
public DataElement(int k, int data, int time) {
key = k;
value = data;
timeStamp = time;
}
}
这种方式的问题是:
使用单链表存储缓存中的元素,链表头部是最近使用的元素,尾部是最久未使用的元素。每次访问或插入元素时,将该元素移到链表头部。
这种方式get和put操作的时间复杂度都是O(n):
我们需要结合双向链表和哈希表来实现LRU缓存。
详细步骤:
下面是一个LRU缓存的Java实现:
public class LRUCache { class Node { int key; int value; Node pre; Node post; } private Hashtable<Integer, Node> cache = new Hashtable<Integer, Node>(); private int count; private int capacity; private Node head, tail; // Add the new node right after head private void addNode(Node 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(Node node) { Node pre = node.pre; Node post = node.post; pre.post = post; post.pre = pre; } // Move node in between to the head private void moveToHead(Node node) { removeNode(node); addNode(node); } // Pop the current tail private Node popTail() { Node res = tail.pre; removeNode(res); return res; } public LRUCache(int capacity) { this.count = 0; this.capacity = capacity; head = new Node(); head.pre = null; tail = new Node(); tail.post = null; head.post = tail; tail.pre = head; } public int get(int key) { Node node = cache.get(key); if (node == null) { return -1; } moveToHead(node); return node.value; } public void put(int key, int value) { Node node = cache.get(key); if (node == null) { Node newNode = new Node(); newNode.key = key; newNode.value = value; cache.put(key, newNode); addNode(newNode); ++count; if (count > capacity) { // Pop the tail Node tailNode = popTail(); cache.remove(tailNode.key); --count; } } else { // Update the value. node.value = value; moveToHead(node); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。