LRU的基本实现原理是hash map + 双向链表
要求get 、set方法的时间复杂度为O(1)
#include <iostream>
#include <unordered_map>
#include <cassert>
using namespace std;
template <typename K, typename V>
struct LListNode {
K key;
V value;
LListNode<K, V>* next;
LListNode<K, V>* pre;
LListNode(K k, V v) : key(k), value(v), next(nullptr), pre(nullptr) { }
};
template <typename K, typename V>
class DDList {
public:
DDList()
: head_(new LListNode<K, V>(-1, -1)), tail_(new LListNode<K, V>(-1, -1)), size_(0)
{
head_->next = tail_;
tail_->pre = head_;
}
DDList(const DDList &) = delete;
DDList& operator= (const DDList &) = delete;
~DDList()
{
LListNode<K, V>* p;
while (((p = head_->next) != tail_)) {
erase(p);
delete p;
}
delete head_;
delete tail_;
}
void append_front(LListNode<K, V>* node)
{
++size_;
node->next = head_->next;
head_->next = node;
node->next->pre = node;
node->pre = head_;
}
LListNode<K, V>* remove_back()
{
assert(size_ != 0);
--size_;
LListNode<K, V>* p = tail_->pre;
p->pre->next = tail_;
tail_->pre = p->pre;
return p;
}
void erase(LListNode<K, V>* node)
{
--size_;
node->pre->next = node->next;
node->next->pre = node->pre;
}
int get_size()
{
return size_;
}
private:
LListNode<K, V>* head_;
LListNode<K, V>* tail_;
int size_;
};
template <typename K, typename V>
class LRUCache {
public:
LRUCache(int capacity) {
cap_ = capacity;
}
int get(K key) {
if (map_cache_.count(key) == 1) {
auto p = map_cache_[key];
cache_.erase(p);
cache_.append_front(p);
return p->value;
}
return -1;
}
void put(K key, V value) {
if (map_cache_.count(key) == 1) {
auto p = map_cache_[key];
p->value = value;
cache_.erase(p);
cache_.append_front(p);
} else {
auto p = new LListNode<K, V>(key, value);
map_cache_[key] = p;
cache_.append_front(p);
if (cache_.get_size() > cap_) {
auto ptr = cache_.remove_back();
map_cache_.erase(ptr->key);
delete ptr;
}
}
}
private:
int cap_;
DDList<K, V> cache_;
unordered_map<K, LListNode<K, V>*> map_cache_;
};
//测试代码
int main() {
LRUCache<int, int>* lRUCache = new LRUCache<int, int>(2);
lRUCache->put(1, 1); // 缓存是 {1=1}
lRUCache->put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache->get(1); // 返回 1
lRUCache->put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache->get(2); // 返回 -1 (未找到)
lRUCache->put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache->get(1); // 返回 -1 (未找到)
lRUCache->get(3); // 返回 3
cout << lRUCache->get(4); // 返回 4
delete lRUCache;
return 0;
}
and 无内存泄露