package com.coding.basic.linklist;
import java.util.Objects;
/**
* 用双向链表实现LRU算法
*
* @author liuxin
*/
public class LRUPageFrame {
private static class Node {
Node prev;
Node next;
int pageNum;
Node() {
}
public boolean hasNext() {
return next != null;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Node)) return false;
Node node = (Node) o;
return Objects.equals(pageNum, node.pageNum);
}
@Override
public int hashCode() {
return Objects.hash(pageNum);
}
}
private int capacity;//最大存储个数
private int cur;//当前存储个数
private Node first;// 链表头
private Node last;// 链表尾
public LRUPageFrame(int capacity) {
this.capacity = capacity;
}
/**
* 获取缓存中对象
*
* @param pageNum
* @return
*/
public void access(int pageNum) {
if(this.cur == 0 ) {
Node node = new Node();
node.pageNum = pageNum;
addFirst(node);
return;
}
if (get(pageNum) != null) {
pop(pageNum);
} else {
Node node = new Node();
node.pageNum = pageNum;
add(node);
}
}
private void add(Node node) {
addFirst(node);
}
private Node get(int pageNum) {
Node val = this.first;
while (val.hasNext()) {
if (val.pageNum == pageNum) {
return val;
}
val = val.next;
}
return null;
}
private void addFirst(Node node) {
if(cur == 0){
this.first = node;
this.last = node;
}else {
Node oldFirst = this.first;
this.first = node;
node.prev = null;
node.next = oldFirst;
oldFirst.prev = node;
}
this.cur++;
if (cur > capacity) {
removeLast();
}
}
private void removeLast(){
Node oldLast = this.last;
this.last = oldLast.prev;
oldLast.prev.next = null;
oldLast = null;
}
/**
* 将节点变成first
*
* @param pageNum
*/
private void pop(int pageNum) {
Node node = this.get(pageNum);
//根据node的位置确定如何位移
if (node.equals(this.first)) {
return;
} else {
Node oldPre = node.prev;
Node oldNext = node.next;
Node oldFirst = this.first;
this.first = node;
node.prev = null;
node.next = oldFirst;
oldPre.next = oldNext;
oldNext.prev = oldPre;
}
}
public String toString() {
StringBuilder buffer = new StringBuilder();
Node node = first;
while (node != null) {
buffer.append(node.pageNum);
node = node.next;
if (node != null) {
buffer.append(",");
}
}
return buffer.toString();
}
}