1.题目描述

2.解题思路
分析:总结构体就是一个循环双链表,带头节点dummy.容量为cap,当插入新节点的时候,插入到头部,当越界需要排除一个节点的时候就删除结尾节点,结尾节点表示最久没有被访问过的节点,涉及哈希表的应用.
3.代码详细注释
cpp
struct Node{
int key;
int value;
Node* prev;
Node* next;
Node(int k=0,int v=0):key(k),value(v){}
};
class LRUCache {
private:
int capacity;
Node * dummy;
unordered_map<int,Node*> key_to_node;
//删除一个节点,在容量满的时候删除一个节点,当然要先根据哈希表直接找到这个节点
void remove(Node* node){
node->prev->next = node->next;
node->next->prev = node->prev;
}
//插入一个节点到首位节点
void pushToFront(Node* node){
node->next = dummy->next;
node->prev = dummy;
node->prev->next = node;
node->next->prev = node;
}
//通过哈希表中的key,找到对应的节点并先删除,再把这个节点移动到链表的头部,并返回这个节点
Node* get_node(int key){
auto it = key_to_node.find(key);//
if (it != key_to_node.end()) { // 先判断是否找到
Node* node = it->second; // 拿到key对应的Node*
remove(node);//删除这个节点
pushToFront(node);//把这个节点插入到前面
return node;
}else{
return NULL;//表示没有key对应的这个value
}
}
public:
LRUCache(int capacity) {
this->capacity = capacity;
dummy = new Node();
dummy->prev = dummy;
dummy->next = dummy;
}
int get(int key) {//这个函数是要把key对应的那个数据,放到队列前面,没有的话就返回-1
Node *node = get_node(key);//此时通过哈希表拿到了key对应的节点
if(node!=NULL){
return node->value;
}else{
return -1;
}
}
void put(int key, int value) {//建立新节点新<key,value>放到链表头部,如果越界了,就删除一个最近未访问的节点,也就是把尾节点删除,如果已经有这个key了,就更新value并移动到头部
auto it = key_to_node.find(key);
if(it!=key_to_node.end()){//如果有对应的key了,先删除节点,然后移动到头部保持最近已经访问
remove(it->second);
pushToFront(it->second);
it->second->value = value;//修改值
}else{//否则就新建一个节点放前面去
Node* node = new Node(key,value);
key_to_node[key] = node;
pushToFront(node);
}
if(key_to_node.size() > capacity){//越界就删除尾巴那个最久没访问的
Node* last_node = dummy->prev;
key_to_node.erase(last_node->key);
remove(last_node);
}
}
};