问题描述:
LRU算法:优先把那些最长时间没使用的对象置换掉。根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
JAVA实现:
测试:
public class preface { public static void main(String[] args) { LRUCache cache = new LRUCache(); cache.set(1, "one"); cache.set(2, "two"); cache.set(3, "three"); cache.set(5, "five"); cache.set(4, "five"); cache.get(2); cache.set(6, "six"); cache.printCache();// 2,3,4,5,6 } }
仓促之下写了个脑残版的,到头来也没能正确运行:
public class LRUCache { private Map<Integer, pair> cache; private int _cur; //计数 private int _capacity; private int _nums = 0; private heap _h; public class pair implements Comparable { public String value; public int num; public pair(int num, String value) { this.num = num; this.value = value; } @Override public int compareTo(Object o) { return num - ((pair) o).num; } } //通过堆来对pairs进行排序 public class heap { public pair[] pairs; private int _cur; public heap() { pairs = new pair[5]; for (int i = 0; i < 5; ++i) { pairs[i] = new pair(0, null); } _cur = 0; } //每次只能修改最上面的pair public pair set(pair p) { pair t = pairs[0]; pairs[0] = p; return t; } public void insert(pair p) { if (_cur < 5) { pairs[_cur] = p; } ++_cur; } public void sort() { Arrays.sort(pairs); } public int find(pair p) { for (int i = 0; i < 5; ++i) { if (pairs[i] == p) { //==比较的是地址,equal比较的是值 return i; } } return -1; } } public LRUCache() { _cur = 0; _capacity = 0; cache = new HashMap<Integer, pair>(); _h = new heap(); } public String get(int key) { ++_cur; if (cache.containsKey(key)) { return cache.get(key).value; } return null; } public void set(int key, String value) { ++_cur; if (!cache.containsKey(key)) { ++_nums; pair p = new pair(_cur, value); if (_nums == _capacity) { pair t = _h.set(p); for (Integer k:cache.keySet()) { if (cache.get(k) == t) { cache.remove(t); break; } } } else { _h.insert(p); } cache.put(key, p); } else { pair p = cache.get(key); int t = _h.find(p); _h.pairs[t].num = _cur; _h.pairs[t].value = value; } _h.sort(); } public void printCache() { System.out.println("print cache usage"); for (Integer key:cache.keySet()) { pair p = cache.get(key); System.out.println("Key:" + key + " Value:" + p.value + " num:" + p.num); } } }
C++实现:
struct DoubleLinkList {
int key;
int value;
DoubleLinkList *next;
DoubleLinkList *pre;
DoubleLinkList(int k, int v) : key(k), value(v), next(NULL), pre(NULL) {};
};
class LRUCache{
public:
LRUCache(int capacity) {
size = capacity;
cacheMap.clear();
head = new DoubleLinkList(0, 0);
tail = new DoubleLinkList(0, 0);
head->next = tail;
tail->pre = head;
}
int get(int key) {
if (cacheMap.find(key) != cacheMap.end()) {
DoubleLinkList *p = cacheMap[key];
spliceNode(p);
addToFront(p);
return p->value;
}
return -1;
}
void set(int key, int value) {
if (cacheMap.find(key) == cacheMap.end()) {
DoubleLinkList *p = NULL;
if (cacheMap.size() == size) {
p = tail->pre;
cacheMap.erase(p->key);
p->key = key;
p->value = value;
spliceNode(p);
addToFront(p);
} else {
p = new DoubleLinkList(key, value);
addToFront(p);
}
cacheMap[key] = p;
} else {
DoubleLinkList *p = cacheMap[key];
p->value = value;
spliceNode(p);
addToFront(p);
}
}
private:
int size;
map<int, DoubleLinkList*> cacheMap;
DoubleLinkList *head, *tail;
void addToFront(DoubleLinkList *p) {
p->pre = head;
p->next = head->next;
head->next->pre = p;
head->next = p;
}
void spliceNode(DoubleLinkList *p) {
p->pre->next = p->next;
p->next->pre = p->pre;
}
};
用list代替双向链表:
struct CacheNode {
int key;
int value;
CacheNode(int k, int v) : key(k), value(v) {
}
};
class LRUCache{
public:
LRUCache(int capacity) {
size = capacity;
}
int get(int key) {
if (cacheMap.find(key) != cacheMap.end()) {
auto it = cacheMap[key];
cacheList.splice(cacheList.begin(), cacheList, it);
cacheMap[key] = cacheList.begin();
return cacheList.begin()->value;
} else {
return -1;
}
}
void set(int key, int value) {
if (cacheMap.find(key) == cacheMap.end()) {
if (cacheList.size() == size) {
cacheMap.erase(cacheList.back().key);
cacheList.pop_back();
}
cacheList.push_front(CacheNode(key, value));
cacheMap[key] = cacheList.begin();
} else {
auto it = cacheMap[key];
it->value = value;
cacheList.splice(cacheList.begin(), cacheList, it);
cacheMap[key] = cacheList.begin();
}
}
private:
int size;
list<CacheNode> cacheList;
unordered_map<int, list<CacheNode>::iterator > cacheMap;
};