手写LRU、LFU
LRU
Least Recently Used
借助链表,表尾是最近访问的数据,表头是最近最久未使用的数据。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| class LRUCache {
private HashMap<Integer,Node> map; private DoubleList cache; int cap; public LRUCache(int capacity) { this.map=new HashMap<Integer,Node>(); this.cache=new DoubleList(); this.cap=capacity; }
private void makeRecently(int key){ Node x=map.get(key); cache.remove(x); cache.addLast(x); }
private void addRecently(int key,int val){ Node x=new Node(key,val); map.put(key,x); cache.addLast(x); }
private void deleteKey(int key){ Node x=map.remove(key); cache.remove(x); }
private void deleteRecently(){ Node x=cache.removeFirst(); map.remove(x.getKey()); } public int get(int key) { if(!map.containsKey(key)){ return -1; } makeRecently(key); return map.get(key).getValue(); } public void put(int key, int value) { if(map.containsKey(key)){ deleteKey(key); addRecently(key,value); }else{ if(map.size()>=cap){ deleteRecently(); } addRecently(key,value); } }
static class Node{ int k; int v; Node pre; Node next; public Node(int k,int v){ this.k=k; this.v=v; } public int getKey(){ return k; } public int getValue(){ return v; } }
static class DoubleList{ Node head,tail; int size; public DoubleList(){ head=new Node(-1,-1); tail=new Node(-1,-1); head.next=tail; tail.pre=head; size=0; }
public void addLast(Node x){ tail.pre.next=x; x.pre=tail.pre; tail.pre=x; x.next=tail; size++; }
public void remove(Node x){ x.pre.next=x.next; x.next.pre=x.pre; size--; }
public Node removeFirst(){ if(head.next==tail){ return null; } Node first=head.next; remove(first); return first; }
public int size(){ return size(); } } }
|
Java内置类型类型LinkedHashMap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class LRUCache { private LinkedHashMap<Integer,Integer> cache; int cap; public LRUCache(int capacity) { this.cache = new LinkedHashMap<>(); this.cap=capacity; }
public int get(int key) { if (!cache.containsKey(key)) { return -1; } makeRecently(key); return cache.get(key); }
public void put(int key, int value) { if(cache.containsKey(key)){ cache.remove(key); cache.put(key, value); }else{ if(cache.size()==cap){ Integer oldestKey = cache.keySet().iterator().next(); cache.remove(oldestKey); } cache.put(key, value); } }
private void makeRecently(int key){ Integer value = cache.get(key); cache.remove(key); cache.put(key, value); } }
|
LFU
Least Frequently Used
将数据按照访问频次排序,淘汰访问频次最低的数据,如果存在多个相同访问频次,淘汰最旧的数据。
未调试成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| class LFUCache {
private HashMap<Integer,Integer> keyToVal; private HashMap<Integer,Integer> keyToFreq; private HashMap<Integer,LinkedHashSet<Integer>> freqToKeys; private Integer minFreq; private Integer cap;
public LFUCache(int capacity) { this.keyToVal=new HashMap<>(); this.keyToFreq=new HashMap<>(); this.freqToKeys=new HashMap<>(); this.minFreq=0; this.cap=capacity; } public int get(int key) { if(!keyToVal.containsKey(key)){ return -1; } increaseFreq(key); return keyToVal.get(key); } public void put(int key, int value) { if(this.cap<=0){ return; } if(keyToVal.containsKey(key)){ keyToVal.put(key,value); increaseFreq(key); return; } if(cap==keyToVal.size()){ removeMinFreqKey(); } keyToVal.put(key,value); keyToFreq.put(key,1); freqToKeys.putIfAbsent(1,new LinkedHashSet<>()); freqToKeys.get(1).add(key); minFreq=1; }
private void removeMinFreqKey() { LinkedHashSet<Integer> keys=freqToKeys.get(minFreq); Integer oldest=keys.iterator().next(); if(keys.size()>1){ keys.remove(oldest); }else{ freqToKeys.remove(minFreq); } keyToVal.remove(oldest); keyToFreq.remove(oldest); }
private void increaseFreq(int key) { int freq=keyToFreq.get(key); keyToFreq.put(key,freq+1); LinkedHashSet<Integer> keys= freqToKeys.get(freq); keys.remove(key); if(keys.size()==0){ freqToKeys.remove(freq); minFreq=freq+1; } freqToKeys.putIfAbsent(freq+1,new LinkedHashSet<>()); freqToKeys.get(freq+1).add(key); } }
|