package com.coding.lru;
/**
* 用双向链表实现LRU算法
* @author liuxin
*
*/
public class LRUPageFrame {
private static class Node {
Node prev;
Node next;
int pageNum;
Node() {
}
}
private int capacity;
private Node first;// 链表头
private Node last;// 链表尾
public LRUPageFrame(int capacity) {
this.capacity = capacity;
}
/**
* 获取缓存中对象
*
* @param key
* @return
*/
public void access(int pageNum) {
if (first == null) {
accessFirst(pageNum);
return;
}
if (capacity > 0) {
accessNormally(pageNum);
capacity --;
} else {
Node node = first;
while(node != null) {
if (node.pageNum == pageNum) {
accessNodeExisting(node);
return;
}
node = node.next;
}
accessNormally(pageNum);
removeLast();
}
}
private void accessNodeExisting(Node node) {
if (node.next == null) { //最后一个元素为要添加的元素
removeLast();
exchangeFirstWithNode(node);
} else if (node.prev != null) { //要添加的元素在中间
Node n = node.next;
Node p = node.prev;
p.next = n;
n.prev = p;
exchangeFirstWithNode(node);
}
}
private void exchangeFirstWithNode(Node node) {
node.next = first;
first.prev = node;
node.prev = null; //忘记这个就会导致找不到第一个添加的元素,测试出现堆溢出
first = node;
}
private void removeLast() {
last = last.prev;
last.next = null;
}
private void accessNormally(int pageNum) {
Node temp = first;
first = new Node();
first.pageNum = pageNum;
first.next = temp;
temp.prev = first;
}
private void accessFirst(int pageNum) {
first = new Node();
first.pageNum = pageNum;
last = first;
capacity --;
}
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();
}
}