LRU(last recent used)
package fighting.algorithm.project;
import java.util.HashMap;
import java.util.Map;
/**
* LRU:即last recent used,最近使用的队列
* <p>
* 作用:
* 用于缓存,当内存满时,删除最近未使用的元素
* <p>
* 操作:
* put(k, v):插入元素,当内存满时需要先做清除。满足O(1)复杂度
* get(k):获取,同时设为最近使用。满足O(1)复杂度
* <p>
* 分析:
* 最近使用关系,可使用元素顺序来表示,即队头是最近使用的,队尾的是最后使用的
* 需要满足快速查询:哈希表
* 满足元素顺序:链表
* <p>
* 结论:
* 使用双向链表作为基础,最近使用的移到队头,内存不足时删除队尾的。双向的目的是做O(1)删除
* 用哈希表来加速查询
*/
public class LRU {
private Map<Integer, Node> map;
private DoubleLinkedList doubleLinkedList;
private int maxSize;
private int size;
public LRU(int maxSize) {
this.maxSize = maxSize;
doubleLinkedList = new DoubleLinkedList();
map = new HashMap<>();
}
/**
* 添加元素并移到队头
* 1、已存在
* 2、已满
* 3、注意移到队头并更新size
*/
public void put(int k, int value) {
if (map.containsKey(k)) {
doubleLinkedList.remove(map.get(k));
} else if (size == maxSize) {
Node deletedNode = doubleLinkedList.removeLast();
map.remove(deletedNode.key);
} else {
size++;
}
Node newNode = new Node(k, value);
doubleLinkedList.addFirst(newNode);
map.put(k, newNode);
}
/**
* 获取元素并移到队头
*/
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
Node node = map.get(key);
doubleLinkedList.remove(node);
doubleLinkedList.addFirst(node);
return node.value;
}
public static void main(String[] args) {
LRU lru = new LRU(3);
lru.put(1, 1);
lru.put(2, 2);
lru.put(3, 3);
lru.put(4, 4);
lru.doubleLinkedList.print();
System.out.println(lru.get(2));
lru.put(5, 5);
lru.doubleLinkedList.print();
}
public static void doubleLinkedListTest() {
Node node1 = new Node(1, 1);
Node node2 = new Node(2, 2);
Node node3 = new Node(3, 3);
Node node4 = new Node(4, 4);
DoubleLinkedList linkedList = new DoubleLinkedList();
linkedList.addFirst(node4);
linkedList.addFirst(node3);
linkedList.addFirst(node2);
linkedList.addFirst(node1);
linkedList.print();
linkedList.removeLast();
linkedList.remove(node1);
linkedList.print();
linkedList.remove(node2);
linkedList.removeLast();
linkedList.print();
}
}
/**
* 链表节点
*/
class Node {
public int key, value;
public Node prev, next;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
/**
* 双向链表
* 注意size为0(空队列),size为1(头尾相同)的情况
* 注意对size做加减操作
*/
class DoubleLinkedList {
private Node head, tail;
private int size;
/**
* 添加到队头
*/
public void addFirst(Node node) {
if (size == 0) {
head = tail = node;
node.prev = node.next = null;
size++;
return;
}
node.next = head;
head.prev = node;
head = node;
size++;
}
/**
* 移除给定元素
*/
public void remove(Node node) {
if (node == tail) {
removeLast();
return;
}
size--;
if (head == node) {
head = node.next;
return;
}
node.prev.next = node.next;
}
/**
* 移除最后一个元素
*/
public Node removeLast() {
if (size == 0) {
return null;
}
if (size == 1) {
Node last = tail;
head = tail = null;
size = 0;
return last;
}
Node last = tail;
Node secondLast = tail.prev;
secondLast.next = null;
tail = secondLast;
size--;
return last;
}
public void print() {
Node node = head;
System.out.println();
while (node != null) {
System.out.println(node.value);
node = node.next;
}
System.out.println();
}
}
发布于 2020/08/23
浏览
次