LFU缓存实现
struct LFUObject {
int freq;
int key;
int value;
LFUObject* next;
LFUObject* prev;
LFUObject() {
freq = 0;
key = 0;
value = 0;
next = NULL;
prev = NULL;
}
};
struct FreqObject {
LFUObject* head;
LFUObject* tail;
FreqObject() {
head = new LFUObject();
tail = new LFUObject();
head->next = tail;
tail->prev = head;
}
~FreqObject() {
delete head;
delete tail;
}
};
class LFUCache {
private:
unordered_map<int, FreqObject*> freq_list;
unordered_map<int, LFUObject*> cache_list;
int capacity;
int min_freq;
void remove(LFUObject* node) {
node->prev->next = node->next;
node->next->prev = node->prev;
// clean if no object and update min_freq
FreqObject* tmp = freq_list[node->freq];
if (tmp->head->next == tmp->tail) {
freq_list.erase(node->freq);
// if update node, min_freq++, if insert node, min_freq = 1
// min_freq++ alwasy > 1
if (this->min_freq == node->freq) {
this->min_freq++;
}
delete tmp;
}
}
void insert(LFUObject* node) {
// each time to update min_freq
if (freq_list.find(node->freq) == freq_list.end()) {
freq_list[node->freq] = new FreqObject();
this->min_freq = min(this->min_freq, node->freq);
}
FreqObject* tmp = freq_list[node->freq];
node->next = tmp->head->next;
node->prev = tmp->head;
tmp->head->next = node;
node->next->prev = node;
}
public:
/*
* @param capacity: An integer
*/LFUCache(int capacity) {
// do intialization if necessary
this->capacity = capacity;
this->min_freq = INT_MAX;
}
/*
* @param key: An integer
* @param value: An integer
* @return: nothing
*/
void set(int key, int value) {
// write your code here
if (cache_list.find(key) == cache_list.end()) {
if (cache_list.size() == this->capacity) {
LFUObject* tmp = freq_list[this->min_freq]->tail->prev;
remove(tmp);
cache_list.erase(tmp->key);
delete tmp;
}
LFUObject* new_lfu = new LFUObject();
new_lfu->key = key;
new_lfu->value = value;
new_lfu->freq = 1;
insert(new_lfu);
cache_list[key] = new_lfu;
} else {
LFUObject* tmp = cache_list[key];
tmp->value = value;
remove(tmp);
tmp->freq++;
insert(tmp);
}
}
/*
* @param key: An integer
* @return: An integer
*/
int get(int key) {
// write your code
if (cache_list.find(key) != cache_list.end()) {
LFUObject* tmp = cache_list[key];
remove(tmp);
tmp->freq++;
insert(tmp);
return tmp->value;
}
return -1;
}
};
second time to implement
struct LFUCacheNode {
int key;
int value;
int visit;
LFUCacheNode *prev;
LFUCacheNode *next;
LFUCacheNode(int k):key(k), value(0), visit(0), prev(NULL), next(NULL){}
};
struct LFUCacheVisit {
int visit;
LFUCacheNode *head;
LFUCacheNode *tail;
LFUCacheVisit(int v) {
visit = v;
head = new LFUCacheNode(0);
tail = new LFUCacheNode(0);
head->next = tail;
tail->prev = head;
}
~LFUCacheVisit() {
delete head;
delete tail;
}
};
class LFUCache {
public:
/*
* @param capacity: An integer
*/LFUCache(int capacity) {
// do intialization if necessary
this->capacity = capacity;
minvisit = 1;
}
/*
* @param key: An integer
* @param value: An integer
* @return: nothing
*/
void set(int key, int value) {
// write your code here
if (nodemaps.find(key) == nodemaps.end()) {
if (nodemaps.size() >= capacity) {
LFUCacheNode *node = visitmaps[minvisit]->tail->prev;
nodemaps.erase(node->key);
deletenode(node);
delete node;
}
nodemaps[key] = new LFUCacheNode(key);
} else {
deletenode(nodemaps[key]);
}
nodemaps[key]->value = value;
addnode(nodemaps[key]);
}
/*
* @param key: An integer
* @return: An integer
*/
int get(int key) {
// write your code here
if (nodemaps.find(key) == nodemaps.end()) {
return -1;
} else {
LFUCacheNode *tmp = nodemaps[key];
deletenode(tmp);
addnode(tmp);
return tmp->value;
}
}
private:
void deletenode(LFUCacheNode *node) {
node->next->prev = node->prev;
node->prev->next = node->next;
// empty()
LFUCacheVisit *tmp = visitmaps[node->visit];
if (tmp->head->next == tmp->tail) {
visitmaps.erase(tmp->visit);
if (minvisit == tmp->visit) {
minvisit++;
}
delete tmp;
}
}
void addnode(LFUCacheNode *node) {
node->visit++;
if (node->visit < minvisit) {
minvisit = node->visit;
}
if (visitmaps.find(node->visit) == visitmaps.end()) {
visitmaps[node->visit] = new LFUCacheVisit(node->visit);
}
LFUCacheVisit *tmp = visitmaps[node->visit];
node->next = tmp->head->next;
tmp->head->next = node;
node->next->prev = node;
node->prev = tmp->head;
}
int capacity;
unordered_map<int, LFUCacheNode*> nodemaps;
unordered_map<int, LFUCacheVisit*> visitmaps;
int minvisit;
};