使用 unordered_map 和 双向链表简单实现的LRU算法,C++实现:第一种是普通写法,第二种是模板类写法。
#include <iostream>
#include <unordered_map>
using namespace std;
struct CacheNode {
int key;
int value;
CacheNode *pre, *next;
CacheNode(int k, int v) : key(k), value(v), pre(nullptr), next(nullptr) {}
};
class LRUCache {
private:
int size;
CacheNode *head, *tail;
unordered_map<int, CacheNode*> mp;
public:
LRUCache(int capacity): size(capacity), head(nullptr), tail(nullptr) {}
void remove(CacheNode *node) {
if (nullptr != node->pre) {
node->pre->next = node->next;
}
else {
head = node->next;
}
if (nullptr != node->next) {
node->next->pre = node->pre;
}
else {
tail = node->pre;
}
}
void setHead(CacheNode *node) {
node->next = head;
node->pre = nullptr;
if (nullptr != head) {
head->pre = node;
}
head = node;
if (nullptr == tail) {
tail = head;
}
}
void set(int key, int value) {
unordered_map<int, CacheNode*>::iterator it = mp.find(key);
if (it != mp.end()) {
CacheNode *node = it->second;
node->value = value;
remove(node);
setHead(node);
}
else {
CacheNode *node = new CacheNode(key, value);
if (mp.size() >= size) {
unordered_map<int, CacheNode*>::iterator it = mp.find(tail->key);
remove(tail);
mp.erase(it);
}
setHead(node);
mp[key] = node;
}
}
int get(int key) {
unordered_map<int, CacheNode*>::iterator it = mp.find(key);
if (it != mp.end()) {
CacheNode *node = it->second;
remove(node);
setHead(node);
return node->value;
}
else {
return -1;
}
}
};
int main(int argc, char **argv) {
LRUCache *lruCache = new LRUCache(2);
lruCache->set(2, 5);
lruCache->set(1, 6);
cout << lruCache->get(2) << endl;
lruCache->set(4, 7);
cout << lruCache->get(1) << endl;
cout << lruCache->get(2) << endl;
system("pause");
return 0;
}
模板类写法
#include <iostream>
#include <unordered_map>
using namespace std;
template <typename T1, typename T2>
class CacheNode {
public:
T1 key;
T2 value;
CacheNode *pre, *next;
CacheNode(T1 k, T2 v) : key(k), value(v), pre(nullptr), next(nullptr) {}
};
template <typename T1, typename T2>
class LRUCache {
private:
int size;
CacheNode<T1, T2> *head, *tail;
unordered_map<T1, CacheNode<T1, T2>*> mp;
public:
LRUCache(int capacity): size(capacity), head(nullptr), tail(nullptr) {}
void remove(CacheNode<T1, T2> *node) {
if (nullptr != node->pre) {
node->pre->next = node->next;
}
else {
head = node->next;
}
if (nullptr != node->next) {
node->next->pre = node->pre;
}
else {
tail = node->pre;
}
}
void setHead(CacheNode<T1, T2> *node) {
node->next = head;
node->pre = nullptr;
if (nullptr != head) {
head->pre = node;
}
head = node;
if (nullptr == tail) {
tail = head;
}
}
void set(T1 key, T2 value) {
unordered_map<T1, CacheNode<T1, T2>*>::iterator it = mp.find(key);
if (it != mp.end()) {
CacheNode<T1, T2> *node = it->second;
node->value = value;
remove(node);
setHead(node);
}
else {
CacheNode<T1, T2> *node = new CacheNode<T1, T2>(key, value);
if (mp.size() >= size) {
unordered_map<T1, CacheNode<T1, T2>*>::iterator it = mp.find(tail->key);
remove(tail);
mp.erase(it);
}
setHead(node);
mp[key] = node;
}
}
void get(T1 key, T2& value) {
unordered_map<T1, CacheNode<T1, T2>*>::iterator it = mp.find(key);
if (it != mp.end()) {
CacheNode<T1, T2> *node = it->second;
remove(node);
setHead(node);
value = node->value;
}
else {
cout << "query value of " << key << " not exist";
}
}
};
int main(int argc, char **argv) {
LRUCache<int, string> *lruCache = new LRUCache<int,string>(2);
lruCache->set(2, "morning");
lruCache->set(1, "evening");
string v1 = "";
lruCache->get(2, v1);
cout << v1.c_str() << endl;
lruCache->set(4, "afternoon");
string v2 = "";
lruCache->get(1, v2);
cout << v2.c_str() << endl;
string v3 = "";
lruCache->get(2, v3);
cout << v3.c_str() << endl;
system("pause");
return 0;
}