带你读《图解算法小抄》九、LRU(1)https://developer.aliyun.com/article/1348201?groupCode=tech_library
class Node { constructor(key, value) { this.key = key; this.value = value; this.prev = null; this.next = null; }} class LRUCache { constructor(capacity) { this.capacity = capacity; this.size = 0; this.cache = new Map(); this.head = new Node(0, 0); // 伪头节点 this.tail = new Node(0, 0); // 伪尾节点 this.head.next = this.tail; this.tail.prev = this.head; } get(key) { if (this.cache.has(key)) { const node = this.cache.get(key); this.moveToHead(node); return node.value; } return -1; } put(key, value) { if (this.cache.has(key)) { const node = this.cache.get(key); node.value = value; this.moveToHead(node); } else { const newNode = new Node(key, value); this.cache.set(key, newNode); this.addToHead(newNode); this.size++; if (this.size > this.capacity) { const tailNode = this.removeFromTail(); this.cache.delete(tailNode.key); this.size--; } } } moveToHead(node) { this.removeFromList(node); this.addToHead(node); } removeFromList(node) { const prevNode = node.prev; const nextNode = node.next; prevNode.next = nextNode; nextNode.prev = prevNode; } addToHead(node) { const nextNode = this.head.next; this.head.next = node; node.prev = this.head; node.next = nextNode; nextNode.prev = node; } removeFromTail() { const tailNode = this.tail.prev; this.removeFromList(tailNode); return tailNode; }}
版本2:有序映射
第一个使用双向链表的实现方法对于学习目的和更好地理解如何在进行set()和get()时实现平均O(1)时间复杂度是很好的。
然而,更简单的方法可能是使用JavaScript的Map对象。Map对象保存键值对,并通过记住键的原始插入顺序来保持原始顺序。我们可以利用这一点,通过删除和重新添加项来将最近使用的项保持在映射的“末尾”。如果缓存容量溢出,位于Map开头的项将首先被驱逐。可以使用map.keys()之类的IterableIterator来检查项的顺序。
带你读《图解算法小抄》九、LRU(3)https://developer.aliyun.com/article/1348199?groupCode=tech_library