LRU 是最近最少使用置换算法,当页面的缓存满时,需要把最久未使用的页面从缓存中清理出去,要求 插入 和 访问都要O(1)的事件复杂度,因为需要用哈希表来储存每一个页面便于随机访问,用双向链表来组织这些页面,可以随机插入删除某一个页面。
class LRUCache {
DoubleList list = new DoubleList();
int cursize = 0;
int size;
Map<Integer,Node> map ;
public LRUCache(int capacity) {
size = capacity; // 最大容量
map = new HashMap<>();
}
public int get(int key) {
if(!map.containsKey(key)){
return -1;
}
Node node = map.get(key);
list.remove(node);//把元素更新到最新
list.insert(node);
return node.value;
}
public void put(int key, int value) {
if(map.containsKey(key)){
Node node = map.get(key);
list.remove(node);//把元素更新到最新
list.insert(node);
node.value = value;
return;
}
if(size == cursize){
map.remove(list.head.next.key);
list.remove(list.head.next);//从表头移除一个元素
cursize--;
}
Node node = new Node(key, value);
map.put(key,node);
list.insert(node);//插入新元素
cursize++;
}
class Node{
Node pre;
Node next;
int value;
int key;
public Node(int key, int value){
this.key = key;
this.value = value;
}
}
class DoubleList{
Node head = new Node(0,0);//表头
Node tail = new Node(0,0);//表尾
public DoubleList(){
head.next = tail;
tail.pre = head;
}
void remove(Node node){//删除指定节点
if(node==null) return;
Node pre = node.pre;
Node next = node.next;
node.pre=null;
node.next = null;
pre.next = next;
next.pre = pre;
}
void insert(Node node){//从表尾插入最新元素
if(node==null) return;
Node pre = tail.pre;
pre.next = node;
node.pre = pre;
tail.pre = node;
node.next = tail;
}
}
}