function LruNode (option) {
this.prev = option.prev;
this.next = option.next;
this.key = option.key;
this.value = option.value;
}
function Cache(option) {
this.capacity = option.capacity;
this.lruRoot = new LruNode({});
this.lruLastNode = this.lruRoot;
this.lruLinkedListLength = 0;
this.lookupTable = { undefined: new LruNode({}) };
this.touch = function (node) {
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = undefined;
node.prev = this.lruLastNode;
this.lruLastNode.next = node;
this.lruLastNode = node;
}
this.insertNode = function (node) {
this.lruLastNode.next = node;
this.lruLastNode = node;
this.lookupTable[node.key] = node;
this.lruLinkedListLength++;
}
this.removeFirstNode = function(){
const k = this.lruRoot.next ? this.lruRoot.next.key : undefined;
this.lruRoot.next.next.prev = this.lruRoot;
this.lruRoot.next = this.lruRoot.next.next;
this.lookupTable[k].value = -1;
this.lruLinkedListLength--;
}
}
Cache.prototype.put = function(key, value) {
if (this.lruLinkedListLength < this.capacity) {
const node = new LruNode({ prev: this.lruLastNode, key: key, value: value });
this.insertNode(node);
} else {
const node = this.lookupTable[key];
if (node && node.value !== -1) {
node.value = value;
if (node !== this.lruLastNode)
this.touch(node);
} else {
this.removeFirstNode();
this.put(key, value);
}
}
}
Cache.prototype.get = function(key) {
const node = this.lookupTable[key];
if (node && node.value !== -1) {
if (node === this.lruLastNode) return node.value;
this.touch(node);
return node.value;
}
return -1;
}
const c = new Cache({ capacity: 2 });
c.put(1, 'A');
c.put(2, 'B');
console.log(c.get(1));
c.put(3, 'C');
console.log(c.get(2));
console.log(c.get(3));
console.log(c.get(1));