一、算法思想:
1、首次适应算法:
首次适应算法从空闲分区的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。
2、最佳适应算法:
从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。为适应此算法,空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。
二、算法代码:
1、首次适应算法:
package Package8;
import java.util.*;
public class FirstFit {
static int totalSpace = 0; // 记录整个内存的空间
public static void main(String[] args) {
System.out.println("输入整数执行相应操作:");
System.out.println("1、初始化内存;");
System.out.println("2、输入作业;");
System.out.println("3、分区回收;");
System.out.println("4、内存信息;");
System.out.println("其他:结束程序");
List<Subregion> subregionList = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
outside:while (true) {
System.out.print("请输入要执行的操作:");
int command = 0;
try{
command = scanner.nextInt();
} catch (Exception e){
System.out.println("请输入整数!");
e.printStackTrace();
}
switch (command){
case 1:
// 初始化
if (totalSpace == 0){
// 初始化分区
System.out.print("请输入初始分区的大小:");
int size = 0;
try{
size = scanner.nextInt();
totalSpace = size;
} catch (Exception e){
System.out.println("请输入整数!");
e.printStackTrace();
}
Subregion subregion = new Subregion(0, size, size, size);
subregionList.add(subregion);
System.out.println("初始化成功!");
} else {
System.out.println("分区已经初始化!");
}
break;
case 2:
// 输入作业
if (totalSpace != 0){
System.out.print("请输入作业名:");
String taskName = scanner.next();
System.out.print("请输入作业大小:");
int taskSize = 0;
try{
taskSize = scanner.nextInt();
} catch (Exception e){
System.out.println("请输入整数!");
e.printStackTrace();
}
if (taskSize == 0){
System.out.println("作业大小不能为0!");
break;
}
int flag = -1; // 用于标记内存是否可以存入作业
// 判断内存中是否有同名的作业
for (Subregion subregion : subregionList) {
if (subregion.task.taskName != null && subregion.task.taskName.equals(taskName)) {
System.out.println("作业名被占用!");
flag = 1;
break;
}
}
if (flag != 1) {
// 遍历所有分区
for (int i = 0; i < subregionList.size(); i++) {
// 判断分区是否可以存下作业
if (subregionList.get(i).freeSpace >= taskSize){
// 存入作业
Task task = new Task();
task.taskName = taskName;
task.taskSize = taskSize;
subregionList.get(i).task = task;
// 修改分区空闲空间
subregionList.get(i).freeSpace = subregionList.get(i).freeSpace - taskSize;
// 动态分区
// 如果刚好存下就不分区,否则剩下的分一个新的分区
if (subregionList.get(i).freeSpace != 0){
Subregion subregion = new Subregion();
subregion.freeSpace = subregionList.get(i).freeSpace;
subregion.startAddress = subregionList.get(i).endAddress - subregionList.get(i).freeSpace;
subregion.endAddress = subregionList.get(i).endAddress;
subregion.partitionSpace = subregionList.get(i).freeSpace;
subregionList.add(subregion);
// 修改原分区信息
subregionList.get(i).endAddress = subregion.startAddress;
subregionList.get(i).partitionSpace = subregionList.get(i).partitionSpace - subregionList.get(i).freeSpace;
subregionList.get(i).freeSpace = 0;
// 将分区按照起始地址排序
sortByStartAddress(subregionList);
}
flag = 0;
System.out.println("存入成功!");
break;
}
}
}
if (flag == -1){
System.out.println("内存不足!");
}
} else {
System.out.println("请初始化分区!");
}
break;
case 3:
// 回收作业
if (totalSpace != 0){
System.out.print("请输入作业名:");
String taskName = scanner.next();
// 判断作业是否存在
int flag = -1; // 用于标记作业是否存在
for (int i = 0; i < subregionList.size(); i++) {
if (subregionList.get(i).task.taskName != null && subregionList.get(i).task.taskName.equals(taskName)){
// 如果只有一个分区,直接回收
if (subregionList.size() == 1){
subregionList.get(i).task = new Task();
subregionList.get(i).partitionSpace = totalSpace;
subregionList.get(i).freeSpace = totalSpace;
System.out.println("回收成功!");
flag = 1;
break;
}
// 将该作业所在的区域变成空闲分区
subregionList.get(i).freeSpace = subregionList.get(i).task.taskSize;
subregionList.get(i).task = new Task();
sortByStartAddress(subregionList);
// 删除总空间为0的分区
deleteSubregion(subregionList);
flag = 0;
break;
}
}
// 合并分区
if (flag == 0){
int num = subregionList.size();
while (num > 0){
for (int i = 0; i < subregionList.size(); i++) {
// 该分区为第一个分区
if (subregionList.get(i).task.taskName == null && i == 0){
// 同时第二个分区也为空,合并
if ((i + 1) < subregionList.size() && subregionList.get(i + 1).task.taskName == null){
// 将两个分区大小合并
subregionList.get(i).endAddress = subregionList.get(i + 1).endAddress;
subregionList.get(i).partitionSpace = subregionList.get(i).endAddress - subregionList.get(i).startAddress;
subregionList.get(i).freeSpace = subregionList.get(i).partitionSpace;
// 将第二个分区大小变成0
subregionList.get(i + 1).startAddress = subregionList.get(i + 1).endAddress;
subregionList.get(i + 1).partitionSpace = 0;
subregionList.get(i + 1).freeSpace = 0;
}
}
// 该分区不是第一个分区
if (subregionList.get(i).task.taskName == null && i != 0){
// 如果该分区的前一个分区为空闲分区
if (subregionList.get(i - 1).task.taskName == null){
// 将该分区合并到前一个分区
subregionList.get(i - 1).endAddress = subregionList.get(i).endAddress;
subregionList.get(i - 1).partitionSpace = subregionList.get(i - 1).endAddress - subregionList.get(i - 1).startAddress;
subregionList.get(i - 1).freeSpace = subregionList.get(i - 1).partitionSpace;
// 该分区大小变成0
subregionList.get(i).startAddress = subregionList.get(i).endAddress;
subregionList.get(i).partitionSpace = 0;
subregionList.get(i).freeSpace = 0;
}
}
}
// 删除分区空间为0的分区
deleteSubregion(subregionList);
num --;
}
System.out.println("回收成功!");
} else if (flag == -1){
System.out.println("作业不存在!");
}
} else {
System.out.println("请初始化分区!");
}
break;
case 4:
// 内存信息
if (totalSpace != 0){
System.out.println("总内存空间:" + totalSpace);
for (Subregion subregion : subregionList) {
System.out.println(subregion);
}
} else {
System.out.println("请初始化分区!");
}
break;
default:
break outside; // 退出外层循环
}
}
scanner.close();
}
/**
* 该方法用于将数组按起始地址排序
*/
public static void sortByStartAddress(List<Subregion> subregionList){
for (int i = 0; i < subregionList.size(); i++) {
for (int j = 0; j + 1 < subregionList.size() - i; j++) {
if (subregionList.get(j).startAddress > subregionList.get(j + 1).startAddress){
Collections.swap(subregionList, j, j + 1);
}
}
}
}
/**
* 该方法用于删除总空间为0的分区
*/
public static void deleteSubregion(List<Subregion> subregionList){
subregionList.removeIf(subregion -> subregion.partitionSpace == 0);
}
// 分区信息
static class Subregion {
private int startAddress; // 起始地址
private int endAddress; // 结束地址
private int partitionSpace; // 该分区的总空间
private int freeSpace; // 空闲空间
Task task = new Task(); // 作业信息
public Subregion(int startAddress, int endAddress, int partitionSpace, int freeSpace) {
this.startAddress = startAddress;
this.endAddress = endAddress;
this.partitionSpace = partitionSpace;
this.freeSpace = freeSpace;
}
public Subregion() {
}
@Override
public String toString() {
String taskInfo = "";
if (task.taskName != null){
taskInfo = " " + "分区中作业信息:\n" + " " + task;
}
return "分区信息:" +
"起始地址:" + startAddress +
", 结束地址:" + endAddress +
", 分区总空间:" + partitionSpace +
", 空闲空间:" + freeSpace + "\n" +
taskInfo;
}
}
// 作业信息
static class Task{
private String taskName; // 作业名
private int taskSize; // 作业大小
@Override
public String toString() {
return "作业名:'" + taskName + '\'' +
", 作业大小: " + taskSize;
}
}
}
2、最佳适应算法:
package Package8;
import java.util.*;
public class BestFit {
static int totalSpace = 0; // 记录整个内存的空间
public static void main(String[] args) {
System.out.println("输入整数执行相应操作:");
System.out.println("1、初始化内存;");
System.out.println("2、输入作业;");
System.out.println("3、分区回收;");
System.out.println("4、内存信息;");
System.out.println("其他:结束程序");
List<Subregion2> subregionList = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
outside:while (true) {
System.out.print("请输入要执行的操作:");
int command = 0;
try{
command = scanner.nextInt();
} catch (Exception e){
System.out.println("请输入整数!");
e.printStackTrace();
}
switch (command){
case 1:
// 初始化
if (totalSpace == 0){
// 初始化分区
System.out.print("请输入初始分区的大小:");
int size = 0;
try{
size = scanner.nextInt();
totalSpace = size;
} catch (Exception e){
System.out.println("请输入整数!");
e.printStackTrace();
}
Subregion2 subregion = new Subregion2(0, size, size, size);
subregionList.add(subregion);
System.out.println("初始化成功!");
} else {
System.out.println("分区已经初始化!");
}
break;
case 2:
// 输入作业
if (totalSpace != 0){
System.out.print("请输入作业名:");
String taskName = scanner.next();
System.out.print("请输入作业大小:");
int taskSize = 0;
try{
taskSize = scanner.nextInt();
} catch (Exception e){
System.out.println("请输入整数!");
e.printStackTrace();
}
if (taskSize == 0){
System.out.println("作业大小不能为0!");
break;
}
int flag = -1; // 用于标记内存是否可以存入作业
// 判断内存中是否有同名的作业
for (Subregion2 subregion : subregionList) {
if (subregion.task.taskName != null && subregion.task.taskName.equals(taskName)) {
System.out.println("作业名被占用!");
flag = 1;
break;
}
}
if (flag != 1) {
// 遍历所有分区
for (int i = 0; i < subregionList.size(); i++) {
// 判断分区是否可以存下作业
if (subregionList.get(i).freeSpace >= taskSize){
// 存入作业
Task2 task = new Task2();
task.taskName = taskName;
task.taskSize = taskSize;
subregionList.get(i).task = task;
// 修改分区空闲空间
subregionList.get(i).freeSpace = subregionList.get(i).freeSpace - taskSize;
// 动态分区
// 如果刚好存下就不分区,否则剩下的分一个新的分区
if (subregionList.get(i).freeSpace != 0){
Subregion2 subregion = new Subregion2();
subregion.freeSpace = subregionList.get(i).freeSpace;
subregion.startAddress = subregionList.get(i).endAddress - subregionList.get(i).freeSpace;
subregion.endAddress = subregionList.get(i).endAddress;
subregion.partitionSpace = subregionList.get(i).freeSpace;
subregionList.add(subregion);
// 修改原分区信息
subregionList.get(i).endAddress = subregion.startAddress;
subregionList.get(i).partitionSpace = subregionList.get(i).partitionSpace - subregionList.get(i).freeSpace;
subregionList.get(i).freeSpace = 0;
// 将分区按照起始地址排序
// sortByStartAddress(subregionList);
// 将空闲分区按空闲空间大小排序
sortByFreeSpace(subregionList);
}
flag = 0;
System.out.println("存入成功!");
break;
}
}
}
if (flag == -1){
System.out.println("内存不足!");
}
} else {
System.out.println("请初始化分区!");
}
break;
case 3:
// 回收作业
if (totalSpace != 0){
System.out.print("请输入作业名:");
String taskName = scanner.next();
// 判断作业是否存在
int flag = -1; // 用于标记作业是否存在
for (int i = 0; i < subregionList.size(); i++) {
if (subregionList.get(i).task.taskName != null && subregionList.get(i).task.taskName.equals(taskName)){
// 如果只有一个分区,直接回收
if (subregionList.size() == 1){
subregionList.get(i).task = new Task2();
subregionList.get(i).partitionSpace = totalSpace;
subregionList.get(i).freeSpace = totalSpace;
System.out.println("回收成功!");
flag = 1;
break;
}
// 将该作业所在的区域变成空闲分区
subregionList.get(i).freeSpace = subregionList.get(i).task.taskSize;
subregionList.get(i).task = new Task2();
sortByStartAddress(subregionList);
// 删除总空间为0的分区
deleteSubregion(subregionList);
flag = 0;
break;
}
}
// 合并分区
if (flag == 0){
int num = subregionList.size();
while (num > 0){
for (int i = 0; i < subregionList.size(); i++) {
// 该分区为第一个分区
if (subregionList.get(i).task.taskName == null && i == 0){
// 同时第二个分区也为空,合并
if ((i + 1) < subregionList.size() && subregionList.get(i + 1).task.taskName == null){
// 将两个分区大小合并
subregionList.get(i).endAddress = subregionList.get(i + 1).endAddress;
subregionList.get(i).partitionSpace = subregionList.get(i).endAddress - subregionList.get(i).startAddress;
subregionList.get(i).freeSpace = subregionList.get(i).partitionSpace;
// 将第二个分区大小变成0
subregionList.get(i + 1).startAddress = subregionList.get(i + 1).endAddress;
subregionList.get(i + 1).partitionSpace = 0;
subregionList.get(i + 1).freeSpace = 0;
}
}
// 该分区不是第一个分区
if (subregionList.get(i).task.taskName == null && i != 0){
// 如果该分区的前一个分区为空闲分区
if (subregionList.get(i - 1).task.taskName == null){
// 将该分区合并到前一个分区
subregionList.get(i - 1).endAddress = subregionList.get(i).endAddress;
subregionList.get(i - 1).partitionSpace = subregionList.get(i - 1).endAddress - subregionList.get(i - 1).startAddress;
subregionList.get(i - 1).freeSpace = subregionList.get(i - 1).partitionSpace;
// 该分区大小变成0
subregionList.get(i).startAddress = subregionList.get(i).endAddress;
subregionList.get(i).partitionSpace = 0;
subregionList.get(i).freeSpace = 0;
}
}
}
// 删除分区空间为0的分区
deleteSubregion(subregionList);
num --;
}
sortByFreeSpace(subregionList);
System.out.println("回收成功!");
} else if (flag == -1){
System.out.println("作业不存在!");
}
} else {
System.out.println("请初始化分区!");
}
break;
case 4:
// 内存信息
if (totalSpace != 0){
System.out.println("总内存空间:" + totalSpace);
for (Subregion2 subregion : subregionList) {
System.out.println(subregion);
}
} else {
System.out.println("请初始化分区!");
}
break;
default:
break outside; // 退出外层循环
}
}
scanner.close();
}
/**
* 该方法用于将分区按起始地址排序
*/
public static void sortByStartAddress(List<Subregion2> subregionList){
for (int i = 0; i < subregionList.size(); i++) {
for (int j = 0; j + 1 < subregionList.size() - i; j++) {
if (subregionList.get(j).startAddress > subregionList.get(j + 1).startAddress){
Collections.swap(subregionList, j, j + 1);
}
}
}
}
/**
* 该方法用于将空闲分区按空闲空间大小排序
* 被占用的分区放到最后
*/
public static void sortByFreeSpace(List<Subregion2> subregionList){
for (int i = 0; i < subregionList.size(); i++) {
for (int j = 0; j + 1 < subregionList.size() - i; j++) {
if (subregionList.get(j).freeSpace > subregionList.get(j + 1).freeSpace){
Collections.swap(subregionList, j, j + 1);
}
}
}
List<Subregion2> list = new ArrayList<>();
Iterator<Subregion2> iterator = subregionList.iterator();
while (iterator.hasNext()){
Subregion2 subregion2 = iterator.next();
if (subregion2.freeSpace == 0){
list.add(subregion2);
iterator.remove();
}
}
subregionList.addAll(list);
}
/**
* 该方法用于删除总空间为0的分区
*/
public static void deleteSubregion(List<Subregion2> subregionList){
subregionList.removeIf(subregion -> subregion.partitionSpace == 0);
}
// 分区信息
static class Subregion2 {
private int startAddress; // 起始地址
private int endAddress; // 结束地址
private int partitionSpace; // 该分区的总空间
private int freeSpace; // 空闲空间
Task2 task = new Task2(); // 作业信息
public Subregion2(int startAddress, int endAddress, int partitionSpace, int freeSpace) {
this.startAddress = startAddress;
this.endAddress = endAddress;
this.partitionSpace = partitionSpace;
this.freeSpace = freeSpace;
}
public Subregion2() {
}
@Override
public String toString() {
String taskInfo = "";
if (task.taskName != null){
taskInfo = " " + "分区中作业信息:\n" + " " + task;
}
return "分区信息:" +
"起始地址:" + startAddress +
", 结束地址:" + endAddress +
", 分区总空间:" + partitionSpace +
", 空闲空间:" + freeSpace + "\n" +
taskInfo;
}
}
// 作业信息
static class Task2{
private String taskName; // 作业名
private int taskSize; // 作业大小
@Override
public String toString() {
return "作业名:'" + taskName + '\'' +
", 作业大小: " + taskSize;
}
}
}