package com.coding.basic.linklist;
/**
* 用双向链表实现LRU算法
*
* @author liuxin
*
*/
public class LRUPageFrame {
private static class Node {
Node prev;
Node next;
int pageNum;
Node() {
}
}
/**
* LRU算法:
*/
private int capacity;
private int size;
private Node first;// 链表头
private Node last;// 链表尾
public LRUPageFrame(int capacity) {
this.capacity = capacity;
}
/**
* 获取缓存中对象
*
* @param key
* @return
*/
public void access(int pageNum) {
Node node = checkExist(pageNum);
//如果这个页面在缓存中存在
if (node != null) {
// 将当前节点移动至第一个
moveTofirst(node);
} else {
//不存在后比较当前是否已经满队列了
if (size < capacity) {
//如果还有空闲队列
// 添加一个节点在栈顶
final Node n = first;
final Node firstNode = new Node();
firstNode.next = n;
firstNode.pageNum = pageNum;
firstNode.prev = null;
this.first = firstNode;
if (n == null) {
last = firstNode;
} else {
n.prev = firstNode;
}
size++;
} else {
//否则,添加一个节点在栈顶,栈底的节点移除
addNode(pageNum);
}
}
}
//如果超出了缓存范围,则添加到栈顶,栈底的节点移除
private void addNode(int pageNum) {
Node node = new Node();
node.pageNum = pageNum;
node.next = first;
first.prev = node;
first = node;
last = last.prev;
last.next = null;
}
/**
* 如果在队列中存在,则移动至首位
* @param node
*/
private void moveTofirst(Node node) {
if(node==first){
return;
}
if(node==last){
first.prev = node;
node.next = first;
first = node;
last = node.prev;
last.next = null;
first.prev = null;
}else{
node.prev.next = node.next;
node.next.prev = node.prev;
node.prev = null;
node.next = first;
first.prev = node;
first = node;
}
}
/**
* 检查是否在队列中存在页数
* @param pageNum
* @return
*/
private Node checkExist(int pageNum) {
Node node = first;
for(int i=0;i<size;i++){
if(pageNum==node.pageNum){
return node;
}
node=node.next;
}
return null;
}
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();
}
}