Lru cache
LRU cache 其實很好理解,就是邊緣人理論
一個 node 如果被不理很久(write or read),那位子滿了就自然要把這個邊緣人 node 趕出去,
這世界就是這麼現實QQ
Requirement
READ O(1)
WRITE O(1)
Map
Linked List
reduce time, increase capcity
Implement LRU Cache
class LRUCacheNode {
key: string;
value: any;
next: LRUCacheNode | null;
prev: LRUCacheNode | null;
constructor(
key: string,
value: string,
next: LRUCacheNode | null = null,
prev: LRUCacheNode | null = null
) {
this.key = key;
this.value = value;
this.next = next;
this.prev = prev;
}
}
export class LRUCache {
size: number;
limit: number;
head: LRUCacheNode | null;
tail: LRUCacheNode | null;
cacheMap: Record<string, LRUCacheNode>;
constructor(limit = 10) {
this.size = 0;
this.limit = limit;
this.head = null;
this.tail = null;
this.cacheMap = {};
}
private detach(node: LRUCacheNode) {
if (node.prev instanceof LRUCacheNode) {
node.prev.next = node.next;
} else {
this.head = node.next;
}
if (node.next instanceof LRUCacheNode) {
node.next.prev = node.prev;
} else {
this.tail = node.prev;
}
}
public write(key: string, value: string) {
const existingNode = this.cacheMap[key];
if (existingNode) {
this.detach(existingNode);
this.size--;
} else if (this.size === this.limit && this.tail) {
delete this.cacheMap[this.tail.key];
this.detach(this.tail);
this.size--;
}
if (!this.head) {
this.head = this.tail = new LRUCacheNode(key, value);
} else {
const node = new LRUCacheNode(key, value, this.head);
this.head.prev = node;
this.head = node;
}
this.cacheMap[key] = this.head;
this.size++;
}
public read(key: string) {
const existingNode = this.cacheMap[key];
if (existingNode) {
const value = existingNode.value;
if (this.head !== existingNode) {
this.write(key, value);
}
return value;
} else {
console.log(`Item not vailable in cache for key ${key}`);
}
}
public clear() {
this.head = null;
this.tail = null;
this.size = 0;
this.cacheMap = {};
}
}
If consecutive cache his(2 or more time) are count as being used
export class LRUCache {
size: number;
limit: number;
head: LRUCacheNode | null;
tail: LRUCacheNode | null;
cacheMap: Record<string, LRUCacheNode>;
constructor(limit = 10) {
this.size = 0;
this.limit = limit;
this.head = null;
this.tail = null;
this.cacheMap = {};
}
private detach(node: LRUCacheNode) {
if (node.prev instanceof LRUCacheNode) {
node.prev.next = node.next;
} else {
this.head = node.next;
}
if (node.next instanceof LRUCacheNode) {
node.next.prev = node.prev;
} else {
this.tail = node.prev;
}
}
public write(key: string, value: string) {
const existingNode = this.cacheMap[key];
/** If the hit is less than twice, the linked-list will not be changed */
if (existingNode && existingNode.hits < 1) {
existingNode.value = value;
existingNode.hits++;
return;
}
if (existingNode) {
this.detach(existingNode);
this.size--;
} else if (this.size === this.limit && this.tail) {
delete this.cacheMap[this.tail.key];
this.detach(this.tail);
this.size--;
}
if (!this.head) {
this.head = this.tail = new LRUCacheNode(key, value);
} else {
const node = new LRUCacheNode(key, value, this.head);
this.head.prev = node;
this.head = node;
}
this.cacheMap[key] = this.head;
this.size++;
}
public read(key: string) {
const existingNode = this.cacheMap[key];
if (existingNode) {
const value = existingNode.value;
if (this.head !== existingNode) {
this.write(key, value);
}
return value;
} else {
console.log(`Item not vailable in cache for key ${key}`);
}
}
public clear() {
this.head = null;
this.tail = null;
this.size = 0;
this.cacheMap = {};
}
}
LRU Cache
By Jay Chou
LRU Cache
- 167