前言
使用栈实现LRU页面置换算法的代码
LRU页面置换算法可以使用基于计数器,或者基于栈两种方式进行实现
基于计数器
若有不当之处,请您指出,您的指点是我的荣幸
代码实现
这里使用双向链表来实现栈
import java.util.Scanner;
/**
* LRU页面置换算法--基于栈
*/
public class LRUStack {
public static void main(String[] args) {
//当链表未达到指定长度时,用来表示链表的长度
int length = 0;
//表示缺页错误次数
int pageFault=0;
//先创建一个头结点
StackSlot head = new StackSlot(null, -1, null);
//表示每次页面进来时,若需要创建节点,该变量作为中转节点
StackSlot nowNode = null;
//表示头结点后的第一个节点
StackSlot firstNode=null;
//表示最后一个节点
StackSlot lastNode=null;
//当需要进行链表节点的变换的时候,以此作为中转
StackSlot tempNode=null;
Scanner sc=new Scanner(System.in);
System.out.println("请输入页面的数量");
//定义页面数量
int num=sc.nextInt();
System.out.println("请输入栈的深度");
//定义栈的深度(其实也就是帧数组的长度)
int frame=sc.nextInt();
//创建页面数组
int[] pageArr=new int[num];
System.out.println("请输入页面序列");
//初始化页面数组
// 1,2,3,4,3,5,3,8,4,7,2,1,0,9,12,33,2,1,6,2,1
for(int i=0;i<num;i++){
pageArr[i]=sc.nextInt();
}
//构建一个链表
for (int i = 0; i < num; i++) {
//此时链表未达到指定长度
if(length==0){
//第一个节点
//新建链表
nowNode=new StackSlot(head,pageArr[i],null);
//链接
head.next=nowNode;
//链表长度+1
length++;
//缺页错误次数+1
pageFault++;
}else if(length==1){
//此时链表有了一个节点
//判断链表中是否有相同页码的页
tempNode=hasSame(head,pageArr[i]);
//如果没有相同页码的页
if(tempNode==null){
//如果没有页码相同的页
lastNode=getLast(head);
//新建一个节点
nowNode=new StackSlot(lastNode,pageArr[i],null);
//链接到链表末尾
lastNode.next=nowNode;
length++;
pageFault++;
}
}else if(length<frame){
//此时链表中已经有两个或两个以上的节点,但是未满
//查看是否有页码相同的页,若有就将该节点返回
tempNode=hasSame(head,pageArr[i]);
//获取最后一个节点
lastNode=getLast(head);
//如果没有页码相同的页
if(tempNode==null){
//如果链表中没有页码相同的页
//新建一个节点
nowNode=new StackSlot(lastNode,pageArr[i],null);
//拿到最后一个节点
lastNode.next=nowNode;
//链表长度+1
length++;
pageFault++;
}else{
//如果有相同页码的页
//如果页码相同的页不是末尾节点的话
if(tempNode.page!=lastNode.page){
//将该节点从链表中删除
tempNode.pre.next=tempNode.next;
tempNode.next.pre=tempNode.pre;
//将该节点链接到末尾
lastNode.next=tempNode;
tempNode.pre=lastNode;
tempNode.next=null;
}
}
}else{
//此时链表已经达到指定长度了,接下来发生缺页错误将进行页面的置换
//检验链表中是否有相同页码的页
tempNode=hasSame(head,pageArr[i]);
//拿到最后一个节点
lastNode=getLast(head);
//如果没有页码相同的页,就要淘汰掉头结点后的第一个节点
if(tempNode==null){
//拿到原先的头结点之后的第一个节点
firstNode=getFirst(head);
//新建一个节点
nowNode=new StackSlot(lastNode,pageArr[i],null);
//淘汰第一个节点
head.next=firstNode.next;
firstNode.next.pre=head;
//将新建节点链接到末尾
lastNode.next=nowNode;
//缺页错误次数+1
pageFault++;
}else{
//如果已经有了相同的页,将该页调到末尾去!
//将该节点从链表中删除
tempNode.pre.next=tempNode.next;
tempNode.next.pre=tempNode.pre;
//链接到末尾
lastNode.next=tempNode;
tempNode.pre=lastNode;
tempNode.next=null;
}
}
}
//打印链表
myPrint(head,pageFault);
}
//查看当前链表中是否已经有此页
public static StackSlot hasSame(StackSlot head, int page) {
while (head!= null) {
if (head.page == page) {
//如果已经有相同的页面在帧数组当中就返回
return head;
}
head = head.next;
}
//没有就返回null
return null;
}
//进行链表的变换的时候,需要将节点链接到最后,所以需要获得最后一个节点
public static StackSlot getLast(StackSlot head){
while(head.next!=null){
head=head.next;
}
return head;
}
//获取头结点后的第一个节点
public static StackSlot getFirst(StackSlot head){
return head.next;
}
//打印链表
public static void myPrint(StackSlot head,int pageFault){
head=head.next;
System.out.print("页面序列-->{ ");
while(head!=null){
System.out.print(head.page+" ");
head=head.next;
}
System.out.println("}");
System.out.println("缺页次数-->"+pageFault);
}
}
/**
* 这个栈是由双向链表实现的
*/
class StackSlot {
//指向前一个节点的地址
StackSlot pre;
//页码
int page;
//指向下一个节点的地址
StackSlot next;
public StackSlot(StackSlot pre, int page, StackSlot next) {
this.pre = pre;
this.next = next;
this.page = page;
}
}