实战:实现一个LRU
Cache
缓存的两个要素: 大小、替换策略
常见替换算法:
- LRU - least recently used,最近最少使用( 淘汰最旧数据)
- LFU- least frequently used,最不经常使用(淘汰频次最少数据)
LRU cache
实战:实现一个LRU
146. LRU缓存
https://leetcode.cn/problems/lru-cache/
哈希表+双向链表
- 双向链表用于按时间顺序保存数据
- 哈希表用于把key映射到链表结点(指针/引用)
0(1)访问:直接检查哈希表
0(1)更新:通过哈希表定位到链表结点,删除该结点(若存在) ,在表头重新插入
0(1)删除:总是淘汰链表末尾结点,同时在哈希表中删除
class LRUCache {
public:
LRUCache(int capacity) {
this->capacity = capacity;
head = new Node();
tail = new Node();
size = 0;
head->next = tail;
tail->pre = head;
}
int get(int key) {
if(h.find(key) == h.end()){
return -1;
}
Node* node = h[key];
remove(node);
insert(head,node);
return node->value;
}
void put(int key, int value) {
if(h.find(key) == h.end()){
Node* node = new Node();
node->key = key;
node->value = value;
h[key] = node;
insert(head,node);
if(h.size() > capacity){
h.erase(tail->pre->key);
remove(tail->pre);
}
}else{
Node* node = h[key];
node->value = value;
remove(node);
insert(head,node);
}
}
private:
struct Node {
int key;
int value;
Node* pre;
Node* next;
};
unordered_map<int,Node*> h;
Node* head;
Node* tail;
int size;
int capacity;
void insert(Node* p,Node* node){
node->next = p->next;
node->pre = p;
p->next->pre = node;
p->next = node;
}
void remove(Node* node){
node->pre->next = node->next;
node->next->pre = node->pre;
}
};
/**
* 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);
*/
#include <bits/stdc++.h>
using namespace std;
class LRUCache
{
unordered_map<int, list<pair<int, int>>::iterator> hash;
list<pair<int, int>> cache;
int size;
public:
LRUCache(int capacity) : size(capacity) {}
int get(int key)
{
auto it = hash.find(key);
if (it == hash.end())
{
return -1;
}
cache.splice(cache.begin(), cache, it->second);
return it->second->second;
}
void put(int key, int value)
{
auto it = hash.find(key);
if (it != hash.end())
{
it->second->second = value;
return cache.splice(cache.begin(), cache, it->second);
}
cache.insert(cache.begin(), make_pair(key, value));
hash[key] = cache.begin();
if (cache.size() > size)
{
hash.erase(cache.back().first);
cache.pop_back();
}
}
};
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习