CPP/计算机组成原理实验代码/Best_Bad_Fit.cpp
2023-05-12 00:34:15 +08:00

431 lines
8.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include<stdio.h>
#include<stdlib.h>
#define N 5
#include<iostream>
using namespace std;
enum STATE
{
F,W
};
struct subAreaNode
{
int addr; // 起始地址
int size; // 分区大小
int taskId; // 作业号
STATE state; // 分区状态
subAreaNode *pre; // 分区前向指针
subAreaNode *nxt; // 分区后向指针
}subHead;
struct PCB
{
char name[8]; //进程名
int arrive_time; //到达时间
int run_time; //运行时间
int finish_time; //完成时间
int zhouzhuan_time; //周转时间
float daiquan_time; //带权周转时间
};
float sumzhouzhuantime,sumdaiquanzhouzhuantime;
struct PCB pcb[N],temp;
void input(); //输入进程
void sort(); //对输入的进程按到达时间进行排序执行
void output(); //输出算法调度时间表
// 初始化空闲分区链
void intSubArea()
{
// 分配初始分区内存
subAreaNode *fir = (subAreaNode *)malloc(sizeof(subAreaNode));
// 给首个分区赋值
fir->addr = 0;
fir->size = 1000; // 内存初始大小
fir->state = F;
fir->taskId = -1;
fir->pre = &subHead;
fir->nxt = NULL;
// 初始化分区头部信息
subHead.pre = NULL;
subHead.nxt = fir;
}
// 最佳适应算法
int BestFit(int taskId, int size)
{
subAreaNode *tar = NULL;
int tarSize = 1000 + 1;
subAreaNode *p = subHead.nxt;
while (p != NULL)
{
// 寻找最佳空闲区间
if (p->state == F && p->size >= size && p->size < tarSize) {
tar = p;
tarSize = p->size;
}
p = p->nxt;
}
if (tar != NULL) {
// 找到要分配的空闲分区
if (tar->size - size <= 10)
{
// 整块分配
tar->state = W;
tar->taskId = taskId;
}
else
{
// 分配大小为size的区间
subAreaNode *node = (subAreaNode *)malloc(sizeof(subAreaNode));
node->addr = tar->addr + size;
node->size = tar->size - size;
node->state = F;
node->taskId = -1;
// 修改分区链节点指针
node->pre = tar;
node->nxt = tar->nxt;
if (tar->nxt != NULL)
{
tar->nxt->pre = node;
}
tar->nxt = node;
// 分配空闲区间
tar->size = size;
tar->state = W;
tar->taskId = taskId;
}
printf("内存分配成功!\n");
return 1;
}
else
{
printf("找不到合适的内存分区,分配失败...\n");
return 0;
}
}
void BadFit(int taskId,int size){ //最坏适应
//最佳块指针
struct subAreaNode *q = NULL;
subAreaNode *node = subHead.nxt;
//首先找到第一个满足条件的空闲块
while(node != NULL){
if(node->state == F && node->size >= size){
q = node;
break;
}
//如果下一个为空则说明没有空闲区可以分配
if(node->nxt == NULL){
printf("分配失败,没有足够的空间!\n");
break;
} else{
node = node->nxt;
}
}
//遍历寻找最佳的空闲块
while(node != NULL){
if(node->state == F && node->size >= size && node->size < q->size){ //空闲的空间
q = node;
}
node = node->nxt;
}
if(q->size < size){ //最佳空闲块的大小小于需求大小
//分配后剩余的空间
struct subAreaNode *p = (struct subAreaNode*)malloc(sizeof(struct subAreaNode));
p->addr = q->addr + size;
p->size = q->size - size;
p->state = F;
p->taskId = -1;
//分配的空间
q->taskId = taskId;
q->size = size;
q->state = W;
//改变节点的连接
p->nxt = q->nxt;
q->nxt = p;
}else if(q->size == size){ //最佳空闲块空间大小和需求相等
q->taskId = taskId;
q->size = size;
q->state = W;
}
}
int freeSubArea(int taskId) // 回收内存
{
int flag = 0;
subAreaNode *p = subHead.nxt, *pp;
while (p != NULL)
{
if (p->state == W && p->taskId == taskId)
{
flag = 1;
if ((p->pre != &subHead && p->pre->state == F)
&& (p->nxt != NULL && p->nxt->state == F))
{
// 情况1合并上下两个分区
// 先合并上区间
pp = p;
p = p->pre;
p->size += pp->size;
p->nxt = pp->nxt;
pp->nxt->pre = p;
free(pp);
// 后合并下区间
pp = p->nxt;
p->size += pp->size;
p->nxt = pp->nxt;
if (pp->nxt != NULL)
{
pp->nxt->pre = p;
}
free(pp);
}
else if ((p->pre == &subHead || p->pre->state == W)
&& (p->nxt != NULL && p->nxt->state == F))
{
// 情况2只合并下面的分区
pp = p->nxt;
p->size += pp->size;
p->state = F;
p->taskId = -1;
p->nxt = pp->nxt;
if (pp->nxt != NULL)
{
pp->nxt->pre = p;
}
free(pp);
}
else if ((p->pre != &subHead && p->pre->state == F)
&& (p->nxt == NULL || p->nxt->state == W))
{
// 情况3只合并上面的分区
pp = p;
p = p->pre;
p->size += pp->size;
p->nxt = pp->nxt;
if (pp->nxt != NULL)
{
pp->nxt->pre = p;
}
free(pp);
}
else
{
// 情况4上下分区均不用合并
p->state = F;
p->taskId = -1;
}
}
p = p->nxt;
}
if (flag == 1)
{
// 回收成功
printf("内存分区回收成功...\n");
return 1;
}
else
{
// 找不到目标作业,回收失败
printf("找不到目标作业,内存分区回收失败...\n");
return 0;
}
}
// 显示空闲分区链情况
void showSubArea()
{
printf("\n");
printf(" 当前的内存分配情况如下: \n");
printf(" W:工作状态 F:空闲状态 \n");
printf("___________________________________________\n");
printf("| 起始地址 | 空间大小 | 工作状态 | 作业号 |\n");
subAreaNode *p = subHead.nxt;
while (p != NULL)
{
printf("___________________________________________\n");
printf(" %3d k |", p->addr);
printf(" %3d k |", p->size);
printf(" %s |", p->state == F ? "F" : "W");
if (p->taskId > 0)
{
printf(" %2d ", p->taskId);
}
else
{
printf(" ");
}
printf("\n");
p = p->nxt;
}
printf("___________________________________________\n");
}
void sort() //按照到达时间对进程进行排序
{
for(int i=0;i<N-1;i++)
{
for(int j=i+1;j<N;j++)
{
if(pcb[i].arrive_time>pcb[j].arrive_time)
{
temp=pcb[i];
pcb[i]=pcb[j];
pcb[j]=temp;
}
}
}
}
void output(int j)
{
int i;
cout<<"进程运行信息如下(FCFS调度算法):"<<endl;
pcb[0].finish_time=pcb[0].arrive_time+pcb[0].run_time;
pcb[0].zhouzhuan_time=pcb[0].finish_time-pcb[0].arrive_time;
pcb[0].daiquan_time=(float)pcb[0].zhouzhuan_time/pcb[0].run_time;
for(i=1;i<j;i++)
{
if(pcb[i].arrive_time>pcb[i-1].finish_time)
{
pcb[i].finish_time=pcb[i].arrive_time+pcb[i].run_time;
pcb[i].zhouzhuan_time=pcb[i].run_time;
pcb[i].daiquan_time=(float)pcb[i].zhouzhuan_time/pcb[i].run_time;
}
else
{
pcb[i].finish_time=pcb[i-1].finish_time+pcb[i].run_time;
pcb[i].zhouzhuan_time=pcb[i].finish_time-pcb[i].arrive_time;
pcb[i].daiquan_time=(float)pcb[i].zhouzhuan_time/pcb[i].run_time;
}
}
for(i=0;i<j;i++)
{
sumzhouzhuantime+=pcb[i].zhouzhuan_time;
sumdaiquanzhouzhuantime+=pcb[i].daiquan_time;
}
printf("****************************************************************\n");
printf("进程名 到达时间 运行时间 完成时间 周转时间 带权周转时间 \n");
printf("****************************************************************\n");
for(i=0;i<j;i++)
{
printf(" %s %d %d %d %d %.2f\n",pcb[i].name,pcb[i].arrive_time,pcb[i].run_time,pcb[i].finish_time,pcb[i].zhouzhuan_time,pcb[i].daiquan_time);
}
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
cout<<"平均周转时间:"<<sumzhouzhuantime/N<<endl;
cout<<"平均带权周转时间:"<<sumdaiquanzhouzhuantime/N<<endl;
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
}
void showProess(int j){
printf("进程输入信息如下:\n");
printf("进程名 到达时间 服务时间\n");
for(int i=0;i<j;i++)
{
printf("%s \t",pcb[i].name);
printf("%d \t",pcb[i].arrive_time);
printf("%d \n",pcb[i].run_time);
}
}
int main()
{
int ope, taskId, size,select,count;
//oep 功能选择 taskId 进程号 size 进程大小 select 分配算法选择 count 计数
// 初始化空闲分区链
intSubArea();
printf(">>>>>>>>>>>>>>>>>>动态分区算法模拟之最佳/最坏适应算法<<<<<<<<<<<<<<<<<<\n") ;
printf(" ____________________________________\n");
printf(" | 1: 最佳适应算法 2: 最坏适应算法 |\n");
printf(" |___________________________________|\n");
printf("请选择分配算法:");
scanf("%d",&select);
// 模拟动态分区分配算法
for(int i=0;i<N;i++){
printf(" ________________________________________________________________\n");
printf(" | 1: 分配内存 2: 回收内存 3.分区情况 4.进程信息 0: 退出 |\n");
printf(" |_______________________________________________________________|\n");
printf("请选择执行的功能:");
scanf("%d", &ope);
if (ope == 0) break;
if (ope == 1) {
// 模拟分配内存
printf("请输入作业号: ");
scanf("%d", &taskId);
printf("请输入进程名:" );
scanf("%s",pcb[i].name);
printf("请输入到达时间:");
scanf("%d",&pcb[i].arrive_time);
printf("请输入要运行时间:");
scanf("%d",&pcb[i].run_time);
printf("请输入需要分配的内存大小(KB) ");
scanf("%d", &size);
count+=1;
// showProess(count);
if (size <= 0)
{
printf("ERROR:分配内存大小必须为正值\n");
continue;
}
switch(select){ //分配算法选择
case 1:
BestFit(taskId,size);
break ;
case 2:
BadFit(taskId,size);
break ;
}
}
else if (ope == 2)
{
// 模拟回收内存
printf("请输入要回收的作业号: ");
scanf("%d", &taskId);
freeSubArea(taskId);
showSubArea();
}
else if(ope==3){
showSubArea(); // 显示空闲分区链情况
}
else if(ope==4){
showProess(count);
output(count);
}
else
{
printf("错误:请输入 0/1/2\n");
}
}
printf("分配算法模拟结束\n");
system("pause");
return 0;
}