c_cpp lru,LRU,设计并实现最近最少使用(LRU)缓存的数据结构。它应该支持以下操作:get和set
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp lru,LRU,设计并实现最近最少使用(LRU)缓存的数据结构。它应该支持以下操作:get和set相关的知识,希望对你有一定的参考价值。
// idea: use a hashtable and a double-linked list.
// every time get or set, check the hashtable first.
// ====================================================================
class LRUCache {
struct Node {
int key;
int value;
Node *prev;
Node *next;
Node(int k, int v) : key(k), value(v), prev(NULL), next(NULL) {}
Node(int k, int v, Node *pre, Node *nxt) :
key(k), value(v), prev(pre), next(nxt) {}
};
unordered_map<int, Node*> mp; // map key to node in double linked list
int capacity;
Node* head;
Node* tail;
public:
LRUCache(int cap) {
capacity = cap;
mp.clear();
head = NULL;
tail = NULL;
}
int get(int k) {
if(mp.find(k) == mp.end()) return -1;
Node *nd = mp[k];
moveNodeToHead(nd);
return mp[k]->value;
}
void set(int k, int v) {
if(mp.find(k) != mp.end()) { // already in hashtable, then move to front
moveNodeToHead(mp[k]);
mp[k]->value = v;
} else {
if(capacity == mp.size()) { // already full, then remove the tail
mp.erase(tail->key);
removeNode(tail);
}
Node *nd = new Node(k, v);
insertToHead(nd);
mp[k] = nd;
}
}
void insertToHead(Node *n) {
if(!head) {
head = n;
tail = n;
} else {
n->next = head;
head->prev = n;
head = n;
}
}
void removeNode(Node *n) {
if(n == head) {
head = head->next;
if(head) head->prev = NULL;
}
else if(n == tail) {
tail = tail->prev;
tail->next = NULL;
}
else {
n->prev->next = n->next;
n->next->prev = n->prev;
}
}
void moveNodeToHead(Node *n) {
if(n == head) return;
if(n == tail) {
tail->prev->next = NULL;
tail = tail->prev;
n->next = head;
head->prev = n;
head = n;
} else {
n->next->prev = n->prev;
n->prev->next = n->next;
n->next = head;
head->prev = n;
head = n;
}
}
};
// ===================== use std::list ================================
struct CacheNode {
int key;
int value;
CacheNode(int k, int v) : key(k), value(v) {}
};
class LRUCache {
private:
list<CacheNode> cacheList; // gist, use list because list in c++ is double-linked list, and it has the "splice" method!
unordered_map<int, list<CacheNode>::iterator> hash;
int size;
public:
LRUCache(int sz) : size(sz) {}
int get(int key) {
if(hash.find(key) == hash.end()) return -1;
else {
// move current node to front, update hash
cacheList.splice(cacheList.begin(), cacheList, hash[key]);
hash[key] = cacheList.begin();
return hash[key]->value;
}
}
void set(int key, int value) {
// not exist
if(hash.find(key) == hash.end()) {
// if list already full, delete tail node
if(size == cacheList.size()) {
hash.erase(cacheList.back().key);
cacheList.pop_back();
}
// insert new node to front, add entry in hash
cacheList.push_front(CacheNode(key, value));
hash[key] = cacheList.begin();
} else {
// update entry in hash, move node to front, update hash
hash[key]->value = value;
cacheList.splice(cacheList.begin(), cacheList, hash[key]);
hash[key] = cacheList.begin();
}
}
};
以上是关于c_cpp lru,LRU,设计并实现最近最少使用(LRU)缓存的数据结构。它应该支持以下操作:get和set的主要内容,如果未能解决你的问题,请参考以下文章