LRU 介绍 https://zhuanlan.zhihu.com/p/52196637
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) {
return -1;
}
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
const leastUsedKey = this.cache.keys().next().value;
this.cache.delete(leastUsedKey);
}
this.cache.set(key, value);
}
}
在构造函数中,我们传入了一个容量参数capacity
,并创建了一个名为cache
的空Map
对象。在get()
方法中,我们首先判断cache
中是否存在该key
,如果不存在则返回-1。如果存在,则将该key对应的值取出,并从cache
中删除该key
,再重新将该key
和其对应的值添加到Map
中,以保证其在Map
中处于最近使用状态。最后,返回该key
对应的值。
在put()
方法中,我们首先判断cache
中是否存在该key
,如果是,则删除该key
。如果cache
已满,则查找cache
中最久未使用的key并删除它。然后,将新的(key, value)
添加到cache中。
需要注意的是,在上述代码中,我们使用了ES6
中的Map
数据结构来存储缓存数据,因为它具有按照插入顺序排序的特性,这样可以避免手动维护一个额外的链表来记录缓存数据的访问时间戳等信息。
基于哈希链表的LRU
javascript
//定义哈希链表节点类
class HashNode {
constructor(key, value) {
this.key = key;
this.value = value;
this.next = null;
this.prev = null;
}
}
//定义LRU缓存类
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.map = new Map();
this.head = new HashNode(null, null);
this.tail = new HashNode(null, null);
this.head.next = this.tail;
this.tail.prev = this.head;
}
//获取数据
get(key) {
if (this.map.has(key)) {
const node = this.map.get(key);
this.moveToHead(node);
return node.value;
}
return -1;
}
//插入数据
put(key, value) {
if (this.map.has(key)) {
const node = this.map.get(key);
node.value = value;
this.moveToHead(node);
} else {
const node = new HashNode(key, value);
this.map.set(key, node);
this.addToHead(node);
if (this.map.size > this.capacity) {
const removedNode = this.removeFromTail();
this.map.delete(removedNode.key);
}
}
}
//将节点插入到链表头部
addToHead(node) {
node.prev = this.head;
node.next = this.head.next;
this.head.next.prev = node;
this.head.next = node;
}
//将节点移动到链表头部
moveToHead(node) {
this.removeNode(node);
this.addToHead(node);
}
//删除节点
removeNode(node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
//从链表尾部删除节点
removeFromTail() {
const node = this.tail.prev;
this.removeNode(node);
return node;
}
}
//测试LRU缓存
const lruCache = new LRUCache(2);
lruCache.put(1, 'value1');
lruCache.put(2, 'value2');
console.log(lruCache.get(1)); //输出value1
lruCache.put(3, 'value3');
console.log(lruCache.get(2)); //输出-1
lruCache.put(4, 'value4');
console.log(lruCache.get(1)); //输出-1
console.log(lruCache.get(3)); //输出value3
console.log(lruCache.get(4)); //输出value4