LRU算法实现思路
根据LRU算法的理念,我们需要:
一个参数来作为容量阈值
一种数据结构来存储数据,同时希望插入、读取、删除操作的时间复杂度都是O(1)。
所以,我们用到的数据结构是:Hashmap+双向链表。
1.利用hashmap的get、put方法O(1)的时间复杂度,快速取、存数据。
2.利用doublelinkedlist的特征(可以访问到某个节点之前和之后的节点),实现O(1)的新增和删除数据。
package com.mico.provider.utils;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName LRUCache
* @Description
* @Author mazhen
* @Date 2023/4/21 14:14
**/
public class LRUCache {
static class Node {
int key;
int value;
Node next;
Node pre;
Node() {}
Node (int key, int value) {
this.key = key;
this.value = value;
}
}
// 双向链表
static class DoubleList {
int size;
Node head;
Node tail;
DoubleList () {
size = 0;
head = new Node();
tail = new Node();
head.next = tail;
tail.pre = head;
}
//节点添加到链表头部
void addFirst(Node node) {
Node temp = head.next;
head.next = node;
node.pre = head;
node.next = temp;
temp.pre = node;
size++;
}
// 移除指定节点
void remove(Node node) {
if (node == null || node.pre == null || node.next == null) {
return;
}
node.pre.next = node.next;
node.next.pre = node.pre;
node.pre = null;
node.next = null;
size--;
}
// 移除链表尾部节点
void remove() {
if (size <= 0) {
return;
}
Node temp = tail.pre;
temp.pre.next = temp.next;
tail.pre = temp.pre;
temp.pre = null;
temp.next = null;
size--;
}
int getSize () {
return size;
}
}
Map<Integer, Node> map;
DoubleList doubleList;
int cap;
LRUCache (int cap) {
map = new HashMap<>();
doubleList = new DoubleList();
this.cap = cap;
}
public int get(int key) {
Node result = map.get(key);
return result == null ? -1 : result.value;
}
public void put (int key, int value) {
Node newNode = new Node(key, value);
if (map.get(key) != null) {
doubleList.remove(map.get(key));
doubleList.addFirst(newNode);
map.put(key, newNode);
return;
}
doubleList.addFirst(newNode);
map.put(key, newNode);
if (doubleList.getSize() > cap) {
map.remove(doubleList.tail.pre.key);
doubleList.remove();
}
}
public static void main(String[] args) {
LRUCache lruCache = new LRUCache(3);
lruCache.put(1,10);
lruCache.put(2,11);
lruCache.put(3,12);
System.out.println(lruCache.get(1));
System.out.println(lruCache.get(2));
System.out.println(lruCache.get(3));
lruCache.put(4,13);
System.out.println();
System.out.println(lruCache.get(1));
System.out.println(lruCache.get(2));
System.out.println(lruCache.get(3));
System.out.println(lruCache.get(4));
}
}