哈希表加上双向链表,可以O(1)操作,链表节点要记录key,用来在删除lru末尾节点时删除哈希表中的。
链表带头节点,方便很多,不用判断是否为空,同时还维护了末尾节点(通过最开始头结点的prev和next指针都指向自己,插入的时候接续保持循环,这样head的prev的指针就是tail指针)。
链表的删除操作和插入到头部操作封装函数,简便很多。
struct Node{
int key;
int val;
Node *prev;
Node *next;
Node(int key_,int val_):key(key_),val(val_),prev(this),next(this){}
};
class LRUCache {
public:
unordered_map<int,Node*> key_ptr;
int size;
int capacity;
Node * head;
LRUCache(int capacity_) {
capacity=capacity_;
size=0;
head=new Node(0,0);
}
void draw_out(Node *ptr){
ptr->prev->next=ptr->next;
ptr->next->prev=ptr->prev;
}
void add_to_front(Node *ptr){
ptr->next=head->next;
head->next->prev=ptr;
head->next=ptr;
ptr->prev=head;
}
void mode_to_front(Node *ptr){
draw_out(ptr);
add_to_front(ptr);
}
int get(int key) {
if(key_ptr.count(key)==0)
return -1;
Node *ptr=key_ptr[key];
mode_to_front(ptr);
return ptr->val;
}
void put(int key, int value) {
if(key_ptr.count(key)!=0){
Node *ptr=key_ptr[key];
ptr->val=value;
mode_to_front(ptr);
return;
}
if(size==capacity){
Node *tail=head->prev;
draw_out(tail);
key_ptr.erase(tail->key);
delete tail;
size--;
}
Node *ptr=new Node(key,value);
key_ptr[key]=ptr;
add_to_front(ptr);
size++;
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/