LRU算法常用于页面置换算法,是为虚拟页式存储管理服务的。他的设计思路是最近使用过的,就认为在将来有很大概率会使用。
现在认定缓存中的数据是key,value形式, 一种实现方式是使用链表,用链表存储key,value,把最近使用到的节点转移到头节点。分析时间复杂度:查找 o(n) , 插入o(1), 删除 o(n)。
这里使用了map进行优化,在缓存中的结点,都保存一组key,TreeNode到map,这样查询的时间变成o(1)。
还有一个是删除结点的优化,理论上删除链表只能是o(n),但是一种思路是这样的:假设要删除的结点后面存在结点, 那么把下一个结点的值拷贝到当前结点, 之后指针改到后一位去。 这样把删除优化到了o(1)。
下面是代码,有错误劳烦指出
package linkedNode;
import java.util.HashMap;
import java.util.Map;
class LinkedNode{
public LinkedNode(int key,int val) {
this.key = key;
this.val = val;
next = null;
}
int key;
int val;
LinkedNode next;
}
public class LRULinkedAndMap {
private int size;
private int count;
private LinkedNode cacheList;
private Map<Integer,LinkedNode> mp;
// 构造方法
public LRULinkedAndMap(int size) {
this.size = size;
this.cacheList = null;
this.mp = new HashMap<>();
}
//set
public void set(int key, int value) {
if (cacheList == null) {
LinkedNode node = new LinkedNode(key, value);
mp.put(key, node);
cacheList = node;
return;
}
if (mp.containsKey(key)) {
LinkedNode node = mp.get(key);
deleteNodeO1(node);
node.next = cacheList;
cacheList = node;
}else{
LinkedNode node = new LinkedNode(key,value);
mp.put(key, node);
node.next = cacheList;
cacheList = node;
count ++;
if (count == size) {
//超出界限
deleteLast();
}
}
}
private void deleteLast() {
LinkedNode node = cacheList;
if(count == 1) cacheList = null;
while (node.next.next != null) {
node = node.next;
}
mp.remove(node.next.key);
node.next = null;
count--;
}
// get
// 如果在map中,就返回,并且将节点提到第一个位置
// 如果不在,返回-1
public int get(int key) {
if (mp.containsKey(key)) {
LinkedNode node = mp.get(key);
deleteNodeO1(node);
node.next = cacheList;
cacheList = node;
return node.val;
}else{
return -1;
}
}
// 删除节点 o(n)
void deleteNode(LinkedNode node) {
LinkedNode pre = cacheList;
if(node == cacheList){
//要删除的点是头节点
cacheList = pre.next;
return;
}
while (pre.next != node) {
pre = pre.next;
}
pre.next = node.next;
}
void deleteNodeO1(LinkedNode node) {
if (node.next != null) {
node.key = node.next.key;
node.val = node.next.val;
node.next = node.next.next;
}else{
// 如果是最后一个那么只能从头去删了
deleteNode(node);
}
}
private void printCache() {
LinkedNode node = cacheList;
System.out.println("cache:");
while (node != null) {
System.out.print(" -> " + node.val);
node = node.next;
}
System.out.println();
}
public static void main(String[] args) {
LRULinkedAndMap lru = new LRULinkedAndMap(3);
System.out.println(lru.get(0));
lru.set(1,100);
lru.set(2,300);
lru.set(4,500);
lru.printCache();
lru.set(1,100);
lru.printCache();
}
}