![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/00fc6917826519ff26883a1a9b2f29d2.png)
/**
* 存储节点
*/
var Node = function(key = null, value = null){
this.key = key;
this.value = value;
this.prev = null;
this.next = null;
}
/**
* @param {number} capacity
*/
var LRUCache = function(capacity) {
this.hashtable = new Map();
//存储容量
this.capacity = capacity;
//size用于维护容量大小,当超过容量大小,需要进行减容
this.size = 0;
//哨兵:头结点,尾节点
this.head = new Node();
this.tail = new Node();
//维护一个双向链表
this.head.next = this.tail;
this.tail.prev = this.head;
};
/**
* @param {number} key
* @return {number}
*/
LRUCache.prototype.get = function(key) {
let node = this.hashtable.get(key);
//未找到,返回-1
if(node == null) {
return -1;
}
//找到节点,需要移动节点,并返回节点的值
this.moveToHead(node);
return node.value;
};
/**
* 将节点移动到头部
*/
LRUCache.prototype.moveToHead = function(node) {
//step:1.断开当前结点所在节点的连接,即移除节点
//step:2.将节点移动到头部
this.removeNode(node);
this.addToHead(node);
}
/**
* 移除节点
*/
LRUCache.prototype.removeNode = function(node, flag) {
let prevNode = node.prev;
let nextNode = node.next;
prevNode.next = nextNode;
nextNode.prev = prevNode;
//节点的前后指针清空
node.prev = null;
node.next = null;
}
/**
* 添加节点到头部位置
*/
LRUCache.prototype.addToHead = function(node) {
let firstNode = this.head.next;
this.head.next = node;
node.prev = this.head;
node.next = firstNode;
firstNode.prev = node;
}
/**
* @param {number} key
* @param {number} value
* @return {void}
*/
LRUCache.prototype.put = function(key, value) {
let node = this.hashtable.get(key);
//有节点,进行更新,无节点,添加新节点到头部位置
if(node != null) {
node.value = value;
//将节点移动到头部
this.moveToHead(node);
return;
}
//无节点,进行新增,添加到链表中和hashtable中, 同时维护capacity
node = new Node(key, value);
this.addToHead(node);
this.hashtable.set(key, node);
this.size++;
//当节点数量大于容量,需要删除尾节点(不是哨兵尾节点),并清除hashtable中对应的key
if(this.size > this.capacity) {
let tailNode = this.tail.prev;
this.removeNode(tailNode);
//hashtable中也要删除对应的key
this.hashtable.delete(tailNode.key);
//删除尾节点后,继续维护size
this.size--;
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* var obj = new LRUCache(capacity)
* var param_1 = obj.get(key)
* obj.put(key,value)
*/
class LRUCache {
private hashtable: Map<number, DoublyLinkedNode>;
private capacity: number;
private size: number;
private head: DoublyLinkedNode;
private tail: DoublyLinkedNode;
constructor(capacity: number) {
this.capacity = capacity;
this.size = 0;
this.hashtable = new Map();
this.head = new DoublyLinkedNode();
this.tail = new DoublyLinkedNode();
//链表相连
this.head.next = this.tail;
this.tail.prev = this.head;
}
get(key: number): number {
let node: DoublyLinkedNode = this.hashtable.get(key);
if(node == null) {
return -1;
}
//找到节点
this.moveToHead(node);
return node.value;
}
put(key: number, value: number): void {
let node: DoublyLinkedNode = this.hashtable.get(key);
if(node != null) {
node.value = value;
//更新到最前面
this.moveToHead(node);
return;
}
//新增节点
node = new DoublyLinkedNode(key, value);
//将节点添加的链表头部,并将key加入到hash表中
this.addToHead(node);
this.hashtable.set(key, node);
this.size++;
if(this.size > this.capacity) {
let tailNode: DoublyLinkedNode = this.tail.prev;
//超过容量,删除链表最后的节点, 删除hash表中该节点对应的key
this.removeNode(tailNode);
this.hashtable.delete(tailNode.key);
this.size--;
}
}
//移动到头部
moveToHead(node: DoublyLinkedNode): void {
this.removeNode(node);
this.addToHead(node);
}
//删除节点
removeNode(node: DoublyLinkedNode): void {
let prevNode: DoublyLinkedNode = node.prev;
let nextNode: DoublyLinkedNode = node.next;
prevNode.next = nextNode;
nextNode.prev = prevNode;
node.next = null;
node.prev = null;
}
//添加到头部节点位置
addToHead(node: DoublyLinkedNode): void {
let firstNode: DoublyLinkedNode = this.head.next;
this.head.next = node;
node.prev = this.head;
firstNode.prev = node;
node.next = firstNode;
}
}
class DoublyLinkedNode {
public key: number;
public value: number;
public next: DoublyLinkedNode;
public prev: DoublyLinkedNode;
constructor(key: number = -1, value: number = -1) {
this.key = key,
this.value = value;
this.next = null;
this.prev = null;
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* var obj = new LRUCache(capacity)
* var param_1 = obj.get(key)
* obj.put(key,value)
*/