package com.coding.basic.linklist;
/**
* 用双向链表实现LRU算法
* @author liuxin
*
*/
public class LRUPageFrame {
private static class Node {
Node prev;
Node next;
int pageNum;
Node() {
}
}
private int capacity;
private int currentSize;
private Node first;// 链表头
private Node last;// 链表尾
public LRUPageFrame(int capacity) {
this.capacity = capacity;
currentSize = 0;
}
/**
* 获取缓存中对象
*
* @param key
* @return
*/
public void access(int pageNum) {
// 判断缓存是否命中
Node n = find(pageNum);
if(n != null){
// 命中,则把节点提到表头
moveNodeToHead(n);
}else{
// 若未命中,新增节点放到表头,如果链表长度超过capacity,移除链表尾部节点
n = new Node();
n.pageNum = pageNum;
if(currentSize >= capacity){
removeLast();
}
addNodeToHead(n);
}
}
private void addNodeToHead(Node n) {
if(first == null){
first = n;
last = n;
}else{
n.next = first;
first.prev = n;
first = n;
}
currentSize++;
}
private void removeLast() {
Node prevN = last.prev;
prevN.next = null;
last.prev = null;
last = prevN;
currentSize--;
}
private void moveNodeToHead(Node n) {
if(n == first){
return ;
}else if(n == last){
Node preN = n.prev;
preN.next = null;
last.prev = null;
last = preN;
}else{
// 中间节点
Node preN = n.prev;
Node nextN = n.next;
preN.next = nextN;
nextN.prev = preN;
}
n.prev = null;
n.next = first;
first.prev = n;
first = n;
}
private Node find(int pageNum) {
Node n = first;
while(n != null){
if(n.pageNum == pageNum){
return n;
}
n = n.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();
}
}