每天一道场景题
带过期时间的LRU实现(更新时不改变expire_time)
put 的时候遍历找过期的,也可以从list->head往后找,这里应该优化不成O(1)吧?
#include <iostream>
#include <unordered_map>
#include <time.h>
using namespace std;
const int ttl=10;
class LRUCache{
public:
struct DLinkNode
{
int key,value;
time_t expire_time;
DLinkNode *prev,*next;
DLinkNode(int key,int value):key(key),value(value),expire_time(0),prev(nullptr),next(nullptr){}
};
int _cap;
unordered_map<int,DLinkNode*> _cache;
DLinkNode *_head,*_tail;
LRUCache(int capacity):_cap(capacity){
_head=new DLinkNode(0,0);
_tail=new DLinkNode(0,0);
_head->next=_tail;
_tail->prev=_head;
}
void removeNode(DLinkNode* tmp){
tmp->prev->next=tmp->next;
tmp->next->prev=tmp->prev;
return ;
}
void addToLast(DLinkNode* tmp){
DLinkNode * pre=_tail->prev;
pre->next=tmp;
tmp->next=_tail;
_tail->prev=tmp;
tmp->prev=pre;
return ;
}
DLinkNode* removeHead(){
DLinkNode* tmp=_head->next;
_head->next=tmp->next;
tmp->next->prev=_head;
return tmp;
}
int get(int key){
if(_cache.find(key)==_cache.end()) return -1;
else{
DLinkNode* tmp=_cache[key];
time_t cur_time;
cur_time=time(nullptr);
if(difftime(cur_time,tmp->expire_time)<=0){
//过期
removeNode(tmp);//链表删
_cache.erase(key);//hash删
return -1;
}else{
//这里也可以重新计算expire_time = cur_time + ttl
removeNode(tmp);
addToLast(tmp);
return tmp->value;
}
}
}
void put(int key,int value){
if(_cache.find(key)!=_cache.end()){
DLinkNode* tmp=_cache[key];
removeNode(tmp);
addToLast(tmp);
//更新值,这里也可以重新计算expire_time = cur_time + ttl
tmp->value=value;
return ;
}else{
DLinkNode* tmp=new DLinkNode(key,value);
time_t cur_time;
cur_time=time(nullptr);
tmp->expire_time=cur_time+ttl;
addToLast(tmp);
_cache[key]=tmp;
bool is_expire=false;
if(_cache.size()>=_cap){
//找第一个过期的删除,O(N)
unordered_map<int,DLinkNode*>::iterator it;
for(;it!=_cache.end();it++){
if(difftime(it->second->expire_time,cur_time)>=0){
is_expire=true;
break;
}
}
if(is_expire){
//找到啦
DLinkNode* tmp=it->second;
removeNode(tmp);
_cache.erase(tmp->key);
}else{
//都没过期
DLinkNode* tmp=removeHead();
_cache.erase(tmp->key);
}
}
}
}
};
查看19道真题和解析