1.我们首先想到快速查询 应该使用哈希表 可以做到快速查询 但是没有固定顺序
2.于是想到又固定顺序还要增加复杂度低 就应该用链表 但是删除做不到常数级别 最终选择双向链表
3.我们可以把双向链表和哈希表得键相映射可以取得联系
2.首先我们应该创建出来一个双向链表
struct Dlist{
int val;
int key;
Dlist* pre;
Dlist* next;
Dlist():val(0),key(0),pre(nullptr),next(nullptr){};
Dlist(int val,int key):val(val),key(key),pre(nullptr),next(nullptr){};
};
1.双向链表尾部就是最近最久未使用得数据 表头是最近经常使用的节点
void moveTohead(Dlist* node) {
removeNode(node);
addNode(node);
}
void removeNode(Dlist* node) {
node->next->pre=node->pre;
node->pre->next=node->next;
}
void addNode(Dlist* node) {
head->next->pre=node;
node->next=head->next;
head->next=node;
node->pre=head;
}
Dlist* moveTail() {
Dlist* temp=tail->pre;
removeNode(temp);
return temp;
}
3.实现put get
struct Dlist{
int val;
int key;
Dlist* pre;
Dlist* next;
Dlist():val(0),key(0),pre(nullptr),next(nullptr){};
Dlist(int val,int key):val(val),key(key),pre(nullptr),next(nullptr){};
};
class LRUCache {
private:
unordered_map<int,Dlist*>mp;
Dlist* head;
Dlist* tail;
int sz;
int capacity;
public:
LRUCache(int capacity):capacity(capacity),sz(0) {
head=new Dlist();
tail=new Dlist();
head->next=tail;
tail->pre=head;
}
int get(int key) {
if (!mp.count(key)) {
return -1;
}
// 如果 key 存在,先通过哈希表定位,再移到头部
Dlist* node = mp[key];
moveTohead(node);
return node->val;
}
void put(int key, int value) {
if(mp.find(key)==mp.end()){
Dlist* pnew=new Dlist(value,key);
mp[key]=pnew;
addNode(pnew);
sz++;
if(sz > capacity) {
Dlist* temp=moveTail();
mp.erase(temp->key);
delete temp;
sz--;
}
}else {
mp[key]->val=value;
moveTohead(mp[key]);
}
}
void moveTohead(Dlist* node) {
removeNode(node);
addNode(node);
}
void removeNode(Dlist* node) {
node->next->pre=node->pre;
node->pre->next=node->next;
}
void addNode(Dlist* node) {
head->next->pre=node;
node->next=head->next;
head->next=node;
node->pre=head;
}
Dlist* moveTail() {
Dlist* temp=tail->pre;
removeNode(temp);
return temp;
}
};
/**
* 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);
*/