内存分区分配–首次适应算法
输入内存的大小和阈值minsize,按照首次适应算法进行连续的分区分配。在划分时,若剩余的内存小于等于minsize,则将整块内存分配给该进程不再进行划分。 根据菜单选择相应的操作:
1.初始化:输入内存的大小和阈值minsize,初始状态下空闲分区名字为“void”。
2.分配:输入申请进程的名字、大小。
- 若可以分配,显示“分配成功!”;
- 若剩余空间不足,显示不分配原因“剩余空间不足,不予分配。”;
- 若剩余的空间通过紧凑技术,可以再分配,提示“是否通过紧凑技术,重新划分?(Y/N)”若选择“Y”,通过紧凑技术重新划分并分配,成功后,显示“分配成功!”若选择“N”,则输出“没有合适的剩余空间,不予分配。”
3.回收:输入回收进程的名字,若有相邻空闲分区,需要合并,并输出“回收成功!”;若输入错误,提示“查无此分区!” 4.显示:显示当前内存的分配状态。
0.退出
其他:输出“输入错误,请重新输入。”
输入格式:
先进行初始化后,按照菜单进行相应的操作。
输出格式:
菜单只显示一次,按照相应的选择输出。
输入样例1:
在这里给出一组输入。例如:
1
1024 5
4
0
输出样例1:
在这里给出相应的输出。例如:
1.初始化
2.分配
3.回收
4.显示
0.退出
请选择:
分区号 分区 起始地址 结束地址 大小 当前状态
1 void 0 1023 1024 空闲
输入样例2:
在这里给出一组输入。例如:
1
1000 5
2
A 100
2
B 200
2
C 150
2
D 250
2
E 200
2
F 95
4
0
输出样例2:
在这里给出相应的输出。例如:
1.初始化
2.分配
3.回收
4.显示
0.退出
请选择:
分配成功!
分配成功!
分配成功!
分配成功!
分配成功!
分配成功!
分区号 分区 起始地址 结束地址 大小 当前状态
1 A 0 99 100 已分配
2 B 100 299 200 已分配
3 C 300 449 150 已分配
4 D 450 699 250 已分配
5 E 700 899 200 已分配
6 F 900 999 100 已分配
输入样例3:
在这里给出一组输入。例如:
1
1000 5
2
A 100
2
B 200
2
C 150
2
D 250
2
E 200
2
F 150
4
0
输出样例3:
在这里给出相应的输出。例如:
1.初始化
2.分配
3.回收
4.显示
0.退出
请选择:
分配成功!
分配成功!
分配成功!
分配成功!
分配成功!
剩余空间不足,不予分配。
分区号 分区 起始地址 结束地址 大小 当前状态
1 A 0 99 100 已分配
2 B 100 299 200 已分配
3 C 300 449 150 已分配
4 D 450 699 250 已分配
5 E 700 899 200 已分配
6 void 900 999 100 空闲
输入样例4:
在这里给出一组输入。例如:
1
1000 5
2
A 100
2
B 200
2
C 150
2
D 250
2
E 200
2
F 150
3
A
4
0
输出样例4:
在这里给出相应的输出。例如:
1.初始化
2.分配
3.回收
4.显示
0.退出
请选择:
分配成功!
分配成功!
分配成功!
分配成功!
分配成功!
剩余空间不足,不予分配。
回收成功!
分区号 分区 起始地址 结束地址 大小 当前状态
1 void 0 99 100 空闲
2 B 100 299 200 已分配
3 C 300 449 150 已分配
4 D 450 699 250 已分配
5 E 700 899 200 已分配
6 void 900 999 100 空闲
输入样例5:
在这里给出一组输入。例如:
1
1000 5
2
A 100
2
B 200
2
C 150
2
D 250
2
E 200
2
F 150
3
A
2
X 150
Y
4
0
输出样例5:
在这里给出相应的输出。例如:
1.初始化
2.分配
3.回收
4.显示
0.退出
请选择:
分配成功!
分配成功!
分配成功!
分配成功!
分配成功!
剩余空间不足,不予分配。
回收成功!
是否通过紧凑技术,重新划分?(Y/N)
分配成功!
分区号 分区 起始地址 结束地址 大小 当前状态
1 B 0 199 200 已分配
2 C 200 349 150 已分配
3 D 350 599 250 已分配
4 E 600 799 200 已分配
5 X 800 949 150 已分配
6 void 950 999 50 空闲
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int choice,merSize = 0,minSize = 0,merSizeStart = 0,resultNumber = 0;
boolean flagTar;
int requireSize = 0,flagNumber = -1;
String proName,strTar;
Scanner sc = new Scanner(System.in);
List<Part> parts = new ArrayList<>();
System.out.println("1.初始化\n" + "2.分配\n" + "3.回收\n" + "4.显示\n" + "0.退出");
System.out.println("请选择:");
choice = sc.nextInt();
while (choice!=0){
switch (choice){
//初始化=>输入内存的大小和阈值minsize,初始状态下空闲分区名字为“void”。
case 1:
merSize = sc.nextInt();
minSize = sc.nextInt();
merSizeStart = merSize;
Part partStart = new Part(-3,"void",0,merSize-1,merSize,"空闲");
parts.add(partStart);
break;
//分配=>输入申请进程的名字、大小
case 2:
if("void".equals(parts.get(0).partName)&&parts.get(0).size == merSizeStart){
parts.remove(0); //删除第一次的void分区
}
proName = sc.next();
requireSize = sc.nextInt();
flagTar = alloction(parts,merSize,minSize,proName,requireSize);
if (flagTar){
System.out.println("是否通过紧凑技术,重新划分?(Y/N)");
strTar = sc.next();
if (strTar.equals("N"))
System.out.println("没有合适的剩余空间,不予分配。");
else {
//直接进行紧凑分配
resultNumber = compact(parts,proName,requireSize,merSize,minSize);
System.out.println("分配成功!");
}
}
if(flagTar) merSize = resultNumber;
else if (merSize - requireSize <= minSize && merSize - requireSize >0) merSize = 0;
else if (merSize - requireSize >0&&resultNumber == 0)
merSize -=requireSize;
else if (resultNumber!=0)merSize = resultNumber;
break;
//回收=>输入回收进程的名字,若有相邻空闲分区,需要合并,并输出“回收成功!”;若输入错误,提示“查无此分区!”
case 3:
int flag = -1;
proName = sc.next();
for (int i = 0; i < parts.size(); i++) {
if (proName.equals(parts.get(i).partName)) {
flag = i;
break;
}
}
if (flag != -1){
//进行内存回收
recovery(parts,flag);
} else
System.out.println("查无此分区!");
break;
//显示=>显示当前内存的分配状态。
case 4:
flagNumber = printList(parts,merSize,minSize,merSizeStart);
if (flagNumber != 0) merSize = flagNumber;
break;
default:
System.out.println("输入错误,请重新输入。");
break;
}
choice = sc.nextInt();
}
}
//分区类Part
static class Part{
int partNumber;
String partName;
int startAddr,endAddr;
int size;
String state;
public Part() {
}
public Part(int partNumber, String partName, int startAddr, int endAddr, int size, String state) {
this.partNumber = partNumber;
this.partName = partName;
this.startAddr = startAddr;
this.endAddr = endAddr;
this.size = size;
this.state = state;
}
public int getPartNumber() {
return partNumber;
}
public void setPartNumber(int partNumber) {
this.partNumber = partNumber;
}
public String getPartName() {
return partName;
}
public void setPartName(String partName) {
this.partName = partName;
}
public int getStartAddr() {
return startAddr;
}
public void setStartAddr(int startAddr) {
this.startAddr = startAddr;
}
public int getEndAddr() {
return endAddr;
}
public void setEndAddr(int endAddr) {
this.endAddr = endAddr;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Part part = (Part) o;
return partNumber == part.partNumber &&
startAddr == part.startAddr &&
endAddr == part.endAddr &&
size == part.size &&
Objects.equals(partName, part.partName) &&
Objects.equals(state, part.state);
}
@Override
public int hashCode() {
return Objects.hash(partNumber, partName, startAddr, endAddr, size, state);
}
}
//分配函数
public static boolean alloction(List<Part> parts,int merSize,int minSize,String proName,int requireSize){
int restSpace = 0,tmp = 0,restSpace01 = 0;
boolean flag = false,flagTmp = false,flag01 = false;
for (int i = 0; i < parts.size(); i++) {
if (parts.get(i).state.equals("空闲")&&parts.get(i).size >= requireSize){
tmp = i;
flagTmp = true;
break;
}
if (parts.get(i).state.equals("空闲"))
restSpace01+=parts.get(i).size;
}
if (flagTmp){
if (parts.get(tmp).size - requireSize <= minSize){
parts.add(tmp,new Part(1,proName,parts.get(parts.size()-1).endAddr+1,
parts.get(parts.size()-1).endAddr+parts.get(tmp).size,parts.get(tmp).size,"已分配"));
parts.get(tmp+1).size = 0;
} else{
parts.add(tmp,new Part(1,proName,parts.get(parts.size()-1).endAddr+1,
parts.get(parts.size()-1).endAddr+requireSize,requireSize,"已分配"));
parts.get(tmp+1).endAddr -= requireSize;
parts.get(tmp+1).size -= requireSize;
}
if (parts.get(tmp+1).size == 0)
parts.remove(tmp+1);
//更新数据
for (int i = 0; i < parts.size(); i++) {
if (i == 0){
parts.get(0).setStartAddr(0);
parts.get(0).setEndAddr(parts.get(0).size-1);
}else {
parts.get(i).startAddr = parts.get(i-1).endAddr + 1;
parts.get(i).endAddr = parts.get(i-1).endAddr + parts.get(i).size ;
}
}
System.out.println("分配成功!");
}else if(restSpace01 >= requireSize){
flag = true;
flag01 = true;
} else if(merSize >= requireSize&& flag01 == false){
if (parts.size() == 0){
if(merSize-requireSize<=minSize)
parts.add(new Part(1,proName,0,merSize-1,merSize,"已分配"));
else
parts.add(new Part(1,proName,0,requireSize-1,requireSize,"已分配"));
}
else{
int startAddr = parts.get(parts.size()-1).size + parts.get(parts.size()-1).startAddr;
if (merSize-requireSize<=minSize){
parts.add(new Part(1,proName,startAddr,startAddr + merSize - 1,merSize,"已分配"));
}else
parts.add(new Part(1,proName,startAddr,startAddr + requireSize - 1,requireSize,"已分配"));
}
System.out.println("分配成功!");
}else {
//循环遍历parts数组,找出“空闲”的被回收的内存区域,再加上没有被分配的内存区域,是否够紧凑分配的
for (Part part : parts) {
if("空闲".equals(part.state))
restSpace += part.size;
}
//空闲资源加上剩下没有被分配的空间是否大于需要的空间
if (restSpace+merSize >= requireSize){
flag = true;
}else{
System.out.println("剩余空间不足,不予分配。");
}
}
return flag;
}
//紧凑分配
public static int compact(List<Part> parts, String proName, int requireSize, int merSize,int minSize){
int flag = 0,restSpace = 0;
flag1:
for (int i = 0; i < parts.size(); i++) {
//可能会报错i+1数组越界,不过问题不大
if (parts.get(i).state.equals("空闲") && i == 0 ){
parts.get(i+1).startAddr = 0;
parts.get(i+1).endAddr = parts.get(i+1).size-1;
merSize += parts.get(i).size;
if (merSize >= requireSize){
//partNumber赋值-1 一会儿作为标志删除对应的空闲区域
parts.get(0).partNumber = -1;
flag = 1;
i++;
continue flag1;
}
}else if (parts.get(i).state.equals("空闲")){
//回收之后造成的碎片化
parts.get(i+1).startAddr = parts.get(i).startAddr;
parts.get(i+1).endAddr = parts.get(i).endAddr + parts.get(i+1).size ;
merSize += parts.get(i).size;
if (merSize >= requireSize){
parts.get(i).partNumber = -1;
flag =1;
i++;
continue flag1;
}
}
}
//对刚才标记partNumber为-1的进程进行删除
for (int i = 0; i < parts.size(); i++) {
if (parts.get(i).partNumber == -1|| parts.get(i).state.equals("空闲")) {
//remove之后数组索引重新从0开始
parts.remove(i);
i--;
}
}
//对各个内存进行更新
for (int i = 0; i < parts.size(); i++) {
if (i != 0){
parts.get(i).startAddr = parts.get(i-1).endAddr + 1;
parts.get(i).endAddr = parts.get(i).startAddr + parts.get(i).size -1;
}
}
merSize -=requireSize;
if(merSize <= minSize){
parts.add(new Part(1,proName,parts.get(parts.size()-1).endAddr+1,
parts.get(parts.size()-1).endAddr+requireSize+merSize,requireSize+merSize,"已分配"));
merSize = 0;
}else
//添加新的请求内存分区
parts.add(new Part(1,proName,parts.get(parts.size()-1).endAddr+1,
parts.get(parts.size()-1).endAddr+requireSize,requireSize,"已分配"));
return merSize;
}
//进行内存回收
public static void recovery(List<Part> parts,int targetIndex){
if(targetIndex == 0 && parts.size() == 1){
parts.get(0).partName = "void";
parts.get(0).state = "空闲";
}else if (targetIndex == 0&&parts.get(targetIndex+1).state.equals("已分配")){
parts.get(0).partName = "void";//开头结尾的判断
parts.get(0).state = "空闲";
}else if (targetIndex == 0&&parts.get(targetIndex+1).state.equals("空闲")){
parts.get(targetIndex).partName = "void";
parts.get(targetIndex).endAddr += parts.get(targetIndex+1).size;
parts.get(targetIndex).size += parts.get(targetIndex+1).size;
parts.remove(targetIndex+1);
}
else if (targetIndex == parts.size()-1&&parts.get(targetIndex-1).state.equals("已分配")){
parts.get(targetIndex).partName = "void";
parts.get(targetIndex).state = "空闲";
}else if (targetIndex == parts.size()-1&&parts.get(targetIndex-1).state.equals("空闲")){
parts.get(targetIndex-1).partName = "void";
parts.get(targetIndex-1).endAddr += parts.get(targetIndex).size;
parts.get(targetIndex-1).size += parts.get(targetIndex).size;
parts.remove(targetIndex);
}
else if (parts.get(targetIndex-1).state.equals("空闲")&&parts.get(targetIndex+1).state.equals("已分配")){
parts.get(targetIndex-1).partName = "void";
parts.get(targetIndex-1).endAddr += parts.get(targetIndex).size;
parts.get(targetIndex-1).size += parts.get(targetIndex).size;
parts.remove(targetIndex);
}else if (parts.get(targetIndex+1).state.equals("空闲")&&parts.get(targetIndex-1).state.equals("已分配")){
parts.get(targetIndex).partName = "void";
parts.get(targetIndex).endAddr += parts.get(targetIndex+1).size;
parts.get(targetIndex).size += parts.get(targetIndex+1).size;
parts.remove(targetIndex+1);
}else if (parts.get(targetIndex-1).state.equals("空闲")&&parts.get(targetIndex+1).state.equals("空闲")){
parts.get(targetIndex-1).partName = "void";
parts.get(targetIndex-1).endAddr = parts.get(targetIndex).size + parts.get(targetIndex+1).size + parts.get(targetIndex-1).endAddr;
parts.get(targetIndex-1).size = parts.get(targetIndex).size + parts.get(targetIndex+1).size + parts.get(targetIndex-1).size;
parts.remove(targetIndex);
parts.remove(targetIndex);
}else {
parts.get(targetIndex).partName = "void";
parts.get(targetIndex).state = "空闲";
}
for (int i = 0; i < parts.size(); i++) {
if (i != 0){
parts.get(i).startAddr = parts.get(i-1).endAddr + 1;
parts.get(i).endAddr = parts.get(i).startAddr + parts.get(i).size -1;
}
}
System.out.println("回收成功!");
}
//打印函数
public static int printList(List<Part> parts,int merSize,int minSize,int initMerSize){
int flag = 0;
for (Part part : parts) {
initMerSize -= part.size;
}
merSize = initMerSize;
//最后查看是否初始的内存资源分配完全
if (merSize != 0&&parts.get(parts.size()-1).partNumber!=-3){
if (parts.get(parts.size()-1).state.equals("空闲")){
parts.get(parts.size()-1).endAddr += merSize;
parts.get(parts.size()-1).size += merSize;
}else
parts.add(new Part(1,"void",parts.get(parts.size()-1).endAddr+1,
parts.get(parts.size()-1).endAddr+merSize,merSize,"空闲"));
}
int i = 1;
System.out.println("分区号 分区 起始地址 结束地址 大小 当前状态");
for (Part part : parts) {
System.out.println(i++ +" "+part.partName+" "+part.startAddr+" "+part.endAddr+" "+part.size+" "+part.state);
}
if(parts.size() != 1&&parts.get(parts.size()-1).state.equals("空闲"))
flag = parts.remove(parts.size()-1).size;
if (parts.size() == 1&&parts.get(0).state.equals("空闲")) flag = parts.get(0).size;
return flag;
}
}