UNPKG

@jyeontu/structure-jyeontu

Version:

javascript实现各种数据结构:堆、优先队列、字典树、LFU缓存……

139 lines (136 loc) 3.8 kB
const LFUNode = function ( key = "", val = "", freq = 0, pre = null, next = null ) { this.key = key; this.val = val; this.freq = freq; this.pre = pre; this.next = next; }; class LFULinkLine{ constructor(node){ this.init(node); } init(node){ let head = new LFUNode("head"); let tail = new LFUNode("tail"); head.next = node; tail.pre = node; node.pre = head; node.next = tail; this.head = head; this.tail = tail; } addNode(node){ this.head.next.pre = node; node.pre = this.head; node.next = this.head.next; this.head.next = node; } removeNode(node){ node.pre.next = node.next; node.next.pre = node.pre; } } /** * @param {number} capacity */ class LFUCache{ constructor(capacity = 100){ this.init(capacity); } init(capacity){ this.capacity = capacity; this.num = 0; this.minFreq = 0; this.kvMap = new Map(); this.freqMap = new Map(); } /** * @param {number} key * @return {number} */ get(key){ if (this.capacity === 0) return -1; if (!this.kvMap.has(key)) return -1; let node = this.kvMap.get(key); let linkLine = this.freqMap.get(node.freq); linkLine.removeNode(node); //清空了 if (linkLine.head.next === linkLine.tail) { this.freqMap.delete(node.freq); if (this.minFreq == node.freq) this.minFreq++; } node.freq++; if (this.freqMap.has(node.freq)) { linkLine = this.freqMap.get(node.freq); linkLine.addNode(node); } else { this.freqMap.set(node.freq, new LFULinkLine(node)); } return node.val; } /** * @param {number} key * @param {number} value * @return {void} */ put (key, value) { if (this.capacity === 0) return; if (this.kvMap.has(key)) { //更新 let node = this.kvMap.get(key); node.val = value; let linkLine = this.freqMap.get(node.freq); linkLine.removeNode(node); if (linkLine.head.next === linkLine.tail) { if (this.minFreq == node.freq) this.minFreq++; this.freqMap.delete(node.freq); } node.freq++; if (this.freqMap.has(node.freq)) { linkLine = this.freqMap.get(node.freq); linkLine.addNode(node); } else { linkLine = new LFULinkLine(node); this.freqMap.set(node.freq, linkLine); } } else { //存入 if (this.capacity == this.num) { //存满 let freq = this.minFreq; let linkLine = this.freqMap.get(freq); let node = linkLine.tail.pre; linkLine.removeNode(node); this.kvMap.delete(node.key); if (linkLine.head.next === linkLine.tail) { this.freqMap.delete(node.freq); } } else { this.num++; } let node = new LFUNode(key, value, 0); this.kvMap.set(key, node); if (this.freqMap.has(0)) { let linkLine = this.freqMap.get(0); linkLine.addNode(node); } else { let linkLine = new LFULinkLine(node); this.freqMap.set(0, linkLine); } this.minFreq = 0; } }; }; /** * Your LFUCache object will be instantiated and called as such: * var obj = new LFUCache(capacity) * var param_1 = obj.get(key) * obj.put(key,value) */ exports.LFUCache = LFUCache;