tjindapitak
11/17/2017 - 3:42 PM

lruCache.js

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));