单链表实现LRU算法
LRU应该是面试中常见的算法题目了,其实实现起来也不是特别的困难,使用的数据结构也是常见的单链表。
下面使用java 实现。
原文:ghsticker的博客
0.什么是LRU
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”
1.思路
首先选择合适的数据结构,这里使用的的单链表。
如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。
如果此数据没有在缓存链表中,又可以分为两种情况:
-
如果此时缓存未满,则将此结点直接插入到链表的头部;
-
如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部
2.实现
/**
* 用链表实行LRU缓存算法
* 思路:1.若缓存数据在链表中,则先找到这个数据,删除,再插入到链表头部
* 2.若缓存数据不在链表中
* 2.1 链表容量满了,则删除最后一个结点,从头部插入新的结点
* 2.2 链表容量没满,则直接从头部插入
*/
public class LRUBaseLinkedList<T> {
//链表最大容量
private final static Integer DEFAULT_CAPACITY = 10;
//头结点
private Node<T> headNode;
//长度
private Integer length;
//容量
private Integer capacity;
public LRUBaseLinkedList() {
this.headNode = new Node<>();
this.length = 0;
this.capacity = DEFAULT_CAPACITY;
}
public LRUBaseLinkedList(Integer capacity) {
this.headNode = new Node<>();
this.length = 0;
this.capacity = capacity;
}
//LRU
public void lru(T data){
Node perNode = findPerNode(data);
if(perNode !=null){
deleteElement(perNode);
insertElementHead(data);
}else{
if(length >= this.capacity){
deleteElementEnd();
}
insertElementHead(data);
}
}
/**
* 删除链表中的最后一个元素
*/
private void deleteElementEnd() {
Node p = headNode;
if(p.next == null)
return;
while (p.next.next != null)
p = p.next;
Node end = p.next;
p.next = null;
end= null;
--length;
}
/**
* 在链表头部插入元素
* @param data
*/
private void insertElementHead(T data) {
Node p = headNode.next;
Node newNode = new Node(data,p);
headNode.next = newNode;
length++;
}
/**
* 删除pernode的下一个结点
* @param perNode
*/
private void deleteElement(Node perNode) {
if(perNode != null){
Node temp = perNode.next;
perNode.next = temp.next;
temp.next = null;
length--;
}
}
/**
* 获取查找元素的前一个结点
* @param data
* @return
*/
private Node findPerNode(T data) {
Node p = headNode;
while (p.next != null){
if(p.next.element == data){
return p;
}
p = p.next;
}
return null;
}
/**
* 打印
*/
private void printAll() {
Node node = headNode.next;
while (node != null){
System.out.print(node.element+" ");
node = node.next;
}
System.out.println();
}
//定义结点
public class Node<T>{
T element;
Node next;
public Node() {
}
public Node(T element, Node next) {
this.element = element;
this.next = next;
}
public T getElement() {
return element;
}
public void setElement(T element) {
this.element = element;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
public static void main(String[] args) {
LRUBaseLinkedList<Integer> linkedList = new LRUBaseLinkedList<>();
Scanner sc = new Scanner(System.in);
while (sc.hasNext()){
linkedList.lru(sc.nextInt());
linkedList.printAll();
}
}
}