LRU算法实现
基于双链表的实现
需要维护的是两个:
- 负责达到快速查找作用的
unodered_map<key, DLinkList*>
,key存放的是键,值存放的是这个键在cache里面的地址,这样查找的时候就能快速找到键并通过值访问地址获取其val了 - 负责记录具体信息和使用记录的cache多个
DlinkList
链接起来的链表。推荐创建一个虚拟头和尾结点,方便管理,越靠近头就越是最近用过,越靠近链表尾部,就代表越久未使用过。
struct DLinkedNode{ //使用记录的双向链表
int key_, value_;
DLinkedNode* pre_;
DLinkedNode* next_;
DLinkedNode():key_(0),value_(0), pre_(nullptr), next_(nullptr){}
DLinkedNode(int key, int value)
:key_(key),
value_(value),
pre_(nullptr),
next_(nullptr){}
};
class LRUCache {
private:
unordered_map<int,DLinkedNode*> cache; //缓存,只是为了更快速的找到
DLinkedNode* head;
DLinkedNode* tail;
size_t size;
size_t cap;
public:
LRUCache(int capacity): cap(capacity),size(0){
head = new DLinkedNode();
tail = new DLinkedNode();
head->next_ = tail;
tail->pre_ = head;
}
int get(int key) {
if(!cache.count(key)) return -1;
DLinkedNode* node = cache[key];
moveToHead(node);
return temp->value_;
}
void put(int key, int value) {
if(!cache.count(key)){ //cache里没有就加结点,cache只是为了快速找到
DLinkedNode* node = new DLinkedNode(key,value);
addToHead(node);
cache[key] = node;
size++;
if(size > cap){
DLinkedNode* removed = removeTail();
cache.erase(removed->key_);
delete removed;
size--;
}
}
else{ //加入的存在了,把它挪到使用记录双向链表的第一个
DLinkedNode* node = cache[key];
temp->value_ = value;
moveToHead(node);
}
}
//一些操作双向链表记录的操作方法
void addToHead(DLinkedNode* node){
node->pre_ = head;
node->next_ = head->next_;
head->next_->pre_ = node;
head->next_ = node;
}
void removeNode(DLinkedNode* node){
node->pre_->next_ = node->next_;
node->next_->pre_ = node->pre_;
}
void moveToHead(DLinkedNode* node){
removeNode(node);
addToHead(node);
}
DLinkedNode* removeTail(){
DLinkedNode* node = tail->pre_;
removeNode(node);
return node;
}
};
/**
* 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);
*/