1、LRU概述
LRU(最近最少使用):淘汰最长时间没有被使用的页面。是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法。发生缺页中断时,选择未使用时间最长的页面置换出去。
2、实现LRU
LeetCode146
使用Hash+双链表:
- Hash:查询数据是否在链表,用来做到O(1)访问元素
- 双链表:保证顺序,head附近:最近使用的;tail附近:最久未使用的
- get操作:
- put操作:
- 容量不够,剔除最后,最前新加
2.key值有,于是替换其值,并移至最前
public class LRUCache {
class LinkNode{
int key;
int val;
LinkNode front;
LinkNode next;
public LinkNode(int key, int val){
this.key = key;
this.val = val;
}
}
Map<Integer, LinkNode> map = new HashMap<>();
int capacity;
LinkNode head = new LinkNode(0,0);
LinkNode tail = new LinkNode(0, 0);
public LRUCache(int capacity){
this.capacity = capacity;
head.next = tail;
tail.front = head;
}
public int get(int key){
if(map.containsKey(key)){
LinkNode node = map.get(key);
moveNodeToTop(node);//别忘了,使用了要移动到头部
return node.val;
}else{
return -1;
}
}
public void put(int key, int value){
//新的,加
if(!map.containsKey(key)){
if(map.size() == capacity) deleteLastNode();
LinkNode newNode = new LinkNode(key, value);
addToHead(newNode);
map.put(key, newNode);//别忘了
//本身就在头部添加的,不需要移动到头部
}else{//旧的,改
LinkNode node = map.get(key);
node.val = value;
moveNodeToTop(node);//更改了,移动到头部
}
}
public void deleteLastNode(){
LinkNode lastNode = tail.front;
lastNode.front.next = tail;
tail.front = lastNode.front;
map.remove(lastNode.key);
}
//移动到头部,1.相邻两节点搭线 2.添加到头部
public void moveNodeToTop(LinkNode node){
node.front.next = node.next;
node.next.front = node.front;
addToHead(node);
}
//将节点添加到头部
public void addToHead(LinkNode node){
LinkNode temp = head.next;
head.next = node;
node.front = head;
node.next = temp;
temp.front = node;
}
}