Design

//hash表 + 双向链表(头代表最新,尾代表老)
function ListNode(key, value) {
	this.key = key
	this.value = value
	this.next = null
	this.prev = null
}

var LRUCache = function (capacity) {
	// 缓存容量
	this.capacity = capacity
	// 哈希表 key -> ListNode
	this.hashTable = {}
	// 缓存数目
	this.count = 0
	// 虚拟头尾
	this.dummyHead = new ListNode()
	this.dummyTail = new ListNode()
	this.dummyHead.next = this.dummyTail
	this.dummyTail.prev = this.dummyHead
}

//若哈希表中没有对应值,返回-1。若存在节点,刷新它的位置,移动到链表头部,返回该节点值
LRUCache.prototype.get = function (key) {
	const node = this.hashTable[key]
	if (!node) return -1
	this.moveToHead(node)
	return node.value
}

LRUCache.prototype.moveToHead = function (node) {
	//从链表中删除该节点
	this.removeFromList(node)
	//将该节点添加到链表的头部
	this.addToHead(node)
}

LRUCache.prototype.removeFromList = function (node) {
	const prev = node.prev
	const next = node.next
	prev.next = next
	next.prev = prev
}

LRUCache.prototype.addToHead = function (node) {
	//插入到虚拟头结点和真实头结点之间,注意顺序,先链接node,再调整指针
	//node的prev指针指向虚拟头结点
	node.prev = this.dummyHead
	//node的next指针指向原来的真实头结点
	node.next = this.dummyHead.next
	//原来的真实头结点的prev指向node
	this.dummyHead.next.prev = node
	//虚拟头结点的next指向node
	this.dummyHead.next = node
}

//对于新数据,创建新节点,存入哈希表,并添加到链表头部(最不优先被淘汰),检查是否超容,决定是否剔除"老家伙"
//对于已有数据,更新数据值,刷新节点位置
LRUCache.prototype.put = function (key, value) {
	const node = this.hashTable[key]
  //insert
	if (!node) {
		const newNode = new ListNode(key, value)
		this.hashTable[key] = newNode
		this.addToHead(newNode)
		this.count++
    //check capacity
		if (this.count > this.capacity) {
			//删除"老家伙",将它从链表尾部删除
			const tailNode = this.dummyTail.prev
			this.removeFromList(tailNode)
			delete this.hashTable[tailNode.key]
			this.count--
		}
  //update
	} else {
		node.value = value
		this.moveToHead(node)
	}
}

Last updated