代码:
class LRUCache {
private:
struct Node{
int key,val;
Node* left,*right;
Node(int _key,int _val):key(_key),val(_val){}
}*L,*R;
unordered_map<int,Node*> hash;
int n;
public:
void remove(struct Node* p){
p->left->right = p->right;
p->right->left = p->left;
//不要delete p;因为有可能我们只是更新一个Node,即:将它从list中remove,然后再insert进来,真正删掉一个节点是在超过capacity时
}
void insert(struct Node* p){
p->right = L->right;
p->left = L;
L->right = p;
p->right->left = p;
}
LRUCache(int capacity) {
n = capacity;//capacity是一个形参,函数结束就销毁了,所以我们用一个n来记录
L = new Node(-1,-1),R = new Node(-1,-1);//定义左右两个节点,用来管理双向链表。
L->right = R,R->left = L;
}
int get(int key) {
if(hash.count(key)==0)return -1;
auto p = hash[key];//p是一个迭代器
remove(p);
insert(p);
return p->val;
}
void put(int key, int value) {
if(hash.count(key)){
auto p = hash[key];
p->val = value;
remove(p);
insert(p);
}
else{
if(n==hash.size()){
auto p = R->left;//p是一个Node
remove(p);
hash.erase(p->key);//erase需要参数key,我们通过Node找到其中的key
delete p;
}
auto q = new Node(key,value);
hash[key] = q;//not hash[key] = value;//hash的value是一个Node
insert(q);//在双向链表中插入时,别忘了在hash中也插入
}
}
};
图解:
L和R是两个指向虚拟左右节点的指针,它们中间管理所有已经在hash表中的key value值以及相邻节点的地址。