样例
样例一:
1
100
0
5
JOB1 10:06 42分钟 55K
JOB2 10:20 30分钟 40K
JOB3 10:30 24分钟 35K
JOB4 10:36 15分钟 25K
JOB5 10:42 12分钟 20K
2
100
0
5
JOB1 10:06 42分钟 55K
JOB2 10:20 30分钟 40K
JOB3 10:30 24分钟 35K
JOB4 10:36 15分钟 25K
JOB5 10:42 12分钟 20K
3
100
0
5
JOB1 10:06 42分钟 55K
JOB2 10:20 30分钟 40K
JOB3 10:30 24分钟 35K
JOB4 10:36 15分钟 25K
JOB5 10:42 12分钟 20K
0样例二:
1
100
0
5
JOB3 10:30 24分钟 35K
JOB1 10:06 42分钟 55K
JOB2 10:20 30分钟 40K
JOB5 10:42 12分钟 20K
JOB4 10:36 15分钟 25K
2
100
0
5
JOB1 8:00 40分钟 35K
JOB2 8:10 30分钟 70K
JOB3 8:15 20分钟 50K
JOB4 8:35 10分钟 25K
JOB5 8:40 5分钟 20K
1
100
0
5
11 8:00 40分钟 35K
21 8:10 30分钟 70K
31 8:15 20分钟 50K
41 8:35 10分钟 25K
51 8:40 5分钟 20K
关键代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct data{
int hour;//当前小时
int min;//当前分钟
}time;
struct node{
char name[20];//进程名
time arrive;//到达就绪队列时间
int zx;//执行时间(预期时间)
int size;
time zhuangru;
time start;//开始执行时间(进程调度)
time finish;//执行完成时间
int zz;//周转时间=完成时间-到达就绪队列时间
float zzxs;//带权周转时间系数=周转时间/执行时间
struct node* next;
};
//内存结构体
typedef struct memory_node{
int size; //内存大小
int address; //内存始址
} memoryNode;
memoryNode memory;
//函数名:in参数:无
node* in(){
//函数功能:输入访问序列信息
int n;
node *q,*head;
head = NULL;
printf("请输入内存大小:");
scanf("%d",&memory.size);
printf("请输入起始地址大小为:");
scanf("%d",&memory.address);
printf("请输入进程数量:");
scanf("%d",&n);
printf("请输入进程的参数:\n");
for(int i=0;i<n;i++)
{
node *p = (node *)malloc(sizeof(node));
p->next = NULL;
scanf("%s %d:%d %d分钟 %dK",&p->name,&p->arrive.hour,&p->arrive.min,&p->zx,&p->size);
if(head == NULL) //尾插法
{
head = p;
q = p;
}
else
{
q->next = p;
q = p;
}
}
return head;
}
void output(node *p) {
//函数功能:按进程执行顺序分别输出每个进程全部结果信息和系统平均时间
int sum=0,count=0;
float sum1=0;
printf("\n模拟进程FCFS调度过程输出结果:\n作业名 到达时间 执行时间(分钟) 装入时间 开始时间 完成时间 周转时间(分钟) 带权周转系数\n");
while(p!=NULL)
{
printf("%5s ",p->name);
printf("%5d:%02d ",p->arrive.hour,p->arrive.min);
printf("%8d(分钟) ",p->zx);
printf("%14d:%02d ",p->zhuangru.hour,p->zhuangru.min);
printf("%6d:%02d ",p->start.hour,p->start.min);
printf("%7d:%02d ",p->finish.hour,p->finish.min);
printf("%7d ",p->zz);
printf("%20.2f\n",p->zzxs);
sum=sum+p->zz;
sum1=sum1+p->zzxs;
count++;
p=p->next;
}
printf("系统平均周转时间为:%.2f\n",sum*1.0/count);
printf("系统平均带权周转系数为:%.2f\n\n",sum1/count);
}
//函数名:FCFS参数:无
void FCFS(){
//函数功能:调用来先服务调度算法(FCFS)
printf("\n***********FCFS多道批处理作业调度***********\n");
node *head = in();
node *h,*q;
h = NULL;
q = head;
while(q!=NULL)//对进程按到达时间先后排序
{
node *p = (node *)malloc(sizeof(node));
*p = *q;
p->next = NULL;
if(h == NULL)
{
h = p;
}
else
{
node *a,*apre;
a = h;
while(a!=NULL)
{
if(p->arrive.hour*60+p->arrive.min<a->arrive.hour*60+a->arrive.min)
break;
apre = a;
a = a->next;
}
if(a == h)
{
p->next = h;
h = p;
}
else
{
p->next = a;
apre->next = p;
}
}
q = q->next;
}
//开始FCFS算法
time now;
node *yx,*dd,*ppre,*fdd,*outcome,*foutcome,*p;//yx:运行队列 dd:等待队列 ppre:p的前驱 fdd:等待队列的尾结点 outcome:结果队列 foutcome:结果队列的尾结点 p:用于遍历h
int space;
now.hour = 0;
now.min = 0;
yx = NULL;
dd = NULL;
outcome = NULL;
space = memory.size;
while(h!=NULL)
{
//每一次大循环都找在自己执行完的时间内并且符合条件的 摘下来
//大循环每次末尾都回收第一个
p = h;
while(p!=NULL)
{
if(yx == NULL)//操作运行队列 两种情况:一是第一次运行 二是等待队列中没有进程
{
h = h->next;
p->next = NULL;
yx = p;
p = h;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min)//(进程到达时间 > 当前时间 )——>更新当前时间
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->zhuangru.hour = now.hour;
yx->zhuangru.min = now.min;
yx->start.hour = now.hour;
yx->start.min = now.min;
space -= yx->size;
}
//在有进程运行的同时,寻找满足条件的进程
//条件是:(1)在进程运行完成之前到达 (2)并且有空间
if(p->arrive.hour*60+p->arrive.min<=yx->start.hour*60+yx->start.min+yx->zx&&space-p->size>=0)
{
//修改装入时间 ,但还不能修改当前时间
if(now.hour*60+now.min>p->arrive.hour*60+p->arrive.min)
{
p->zhuangru.hour = now.hour;
p->zhuangru.min = now.min;
}
else
{
p->zhuangru.hour = p->arrive.hour;
p->zhuangru.min = p->arrive.min;
}
space -= p->size;
//把要装入主存的进程从队列中取下接到等待队列中
if(p == h)
{
h = h->next;
p->next =NULL;
if(dd == NULL)
{
dd = p;
fdd = dd;
}
else
{
fdd->next = p;
fdd = p;
}
p = h;
}
else
{
ppre->next = p->next;
p->next = NULL;
if(dd == NULL)
{
dd = p;
fdd = dd;
}
else
{
fdd->next = p;
fdd = p;
}
p = ppre->next;
}
}
else//不满足条件继续遍历 h
{
ppre = p;
p = p->next;
}
}
//回收资源(即开始运行进程)
node *k;
k = yx;
yx = yx->next;
k->start.hour = now.hour;
k->start.min = now.min;
now.hour = k->start.hour+(k->start.min+k->zx)/60;
now.min = (k->start.min+k->zx)%60;
k->finish.hour = now.hour;
k->finish.min = now.min;
k->zz = k->finish.hour*60+k->finish.min-k->arrive.hour*60-k->arrive.min;//计算周转时间
k->zzxs = k->zz*1.0/k->zx;//计算周转系数
space += k->size;//回收空间
//将运行完的进程记录在outcome中,以便后续打印
if(outcome == NULL)
{
outcome = k;
foutcome = outcome;
}
else
{
foutcome->next = k;
foutcome = k;
}
//从等待队列中取进程到运行队列中,并更新当前时间
if(yx == NULL&&dd!=NULL)
{
node *y;
y = dd;
dd = dd->next;
y->next = NULL;
yx = y;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min) //更新now
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->start.hour = now.hour;
yx->start.min = now.min;
}
}
//等待队列和运行队列可能不为空
//将等待队列中的结点放入到运行队列中
while(1)
{
node *k;
k = yx;
yx = yx->next;
k->start.hour = now.hour;
k->start.min = now.min;
now.hour = k->start.hour+(k->start.min+k->zx)/60;
now.min = (k->start.min+k->zx)%60;
k->finish.hour = now.hour;
k->finish.min = now.min;
k->zz = k->finish.hour*60+k->finish.min-k->arrive.hour*60-k->arrive.min;
k->zzxs = k->zz*1.0/k->zx;
space += k->size;
if(outcome == NULL)
{
outcome = k;
foutcome = outcome;
}
else
{
foutcome->next = k;
foutcome = k;
}
if(yx == NULL&&dd!=NULL)
{
node *y;
y = dd;
dd = dd->next;
y->next = NULL;
yx = y;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min) //更新now
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->start.hour = now.hour;
yx->start.min = now.min;
}
if(yx == NULL&&dd == NULL)
break;
}
output(outcome);
}
//函数名:SPF参数:无
void SPF(){
//函数功能:调用最短作业优先算法(SPF)
printf("\n***********SPF多道批处理作业调度***********\n");
node *head = in();
node *h,*q;
h = NULL;
q = head;
while(q!=NULL)//对进程按到达时间先后排序
{
node *p = (node *)malloc(sizeof(node));
*p = *q;
p->next = NULL;
if(h == NULL)
{
h = p;
}
else
{
node *a,*apre;
a = h;
while(a!=NULL)
{
if(p->arrive.hour*60+p->arrive.min<a->arrive.hour*60+a->arrive.min)
break;
apre = a;
a = a->next;
}
if(a == h)
{
p->next = h;
h = p;
}
else
{
p->next = a;
apre->next = p;
}
}
q = q->next;
}
//开始SPF算法
time now;
node *yx,*dd,*ppre,*fdd,*outcome,*foutcome,*p,*pp;
int space;
now.hour = 0;
now.min = 0;
yx = NULL;
dd = NULL;
outcome = NULL;
space = memory.size;
while(h!=NULL)
{
//每一次大循环都找在自己执行完的时间内并且符合条件的 摘下来
//大循环每次末尾都回收第一个
pp = h;
if(yx == NULL)//操作运行队列 两种情况:一是第一次运行 二是等待队列中没有进程
{
h = h->next;
pp->next = NULL;
yx = pp;
pp = h;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min)//(进程到达时间 > 当前时间 )——>更新当前时间
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->zhuangru.hour = now.hour;
yx->zhuangru.min = now.min;
yx->start.hour = now.hour;
yx->start.min = now.min;
space -= yx->size;
}
//寻找满足条件的进程
//对队列按运行时间的大小排序(短进程在前) ,得到队列:duilie
node *w,*duilie,*prew,*ww;//w:遍历h duilie:排序后的队列 prew:记录ww的前驱 ww:遍历duilie(找合适的位置插入结点)
w = h;
duilie = NULL;
while(w!=NULL)
{
node *o = (node *)malloc(sizeof(node));
*o = *w;
o->next = NULL;
if(duilie==NULL)
{
duilie = o;
}
else
{
ww = duilie;
while(ww!=NULL)
{
if(o->zx<ww->zx)
break;
prew = ww;
ww = ww->next;
}
if(ww==duilie)
{
o->next = duilie;
duilie = o;
}
else
{
o->next = ww;
prew->next = o;
}
}
w = w->next;
}
//在排序后的队列duilie中寻找满足条件的进程
p = duilie;
while(p!=NULL)
{
//在有进程运行的同时,寻找满足条件的进程
//条件是:(1)在进程运行完成之前到达 (2)并且有空间
if(p->arrive.hour*60+p->arrive.min<=yx->start.hour*60+yx->start.min+yx->zx&&space-p->size>=0)
{
space -= p->size;
//删除h上的结点
node *check,*precheck;//摘下
check = h;
while(check!=NULL)
{
if(strcmp(p->name,check->name)==0)
break;
precheck = check;
check = check->next;
}
if(check==h)
{
h = h->next;
}
else
{
precheck->next = check->next;
}
check->next = NULL;
if(dd == NULL)//把摘下的进程放入等待队列
{
dd = check;
fdd = dd;
}
else
{
fdd->next = check;
fdd = check;
}
//修改装入时间
if(now.hour*60+now.min>check->arrive.hour*60+check->arrive.min)
{
check->zhuangru.hour = now.hour;
check->zhuangru.min = now.min;
}
else
{
check->zhuangru.hour = check->arrive.hour;
check->zhuangru.min = check->arrive.min;
}
}
p = p->next;
}
//回收资源(即开始运行进程)
node *k;
k = yx;
yx = yx->next;
k->start.hour = now.hour;
k->start.min = now.min;
now.hour = k->start.hour+(k->start.min+k->zx)/60;
now.min = (k->start.min+k->zx)%60;
k->finish.hour = now.hour;
k->finish.min = now.min;
k->zz = k->finish.hour*60+k->finish.min-k->arrive.hour*60-k->arrive.min;//计算周转时间
k->zzxs = k->zz*1.0/k->zx;//计算周转系数
space += k->size;//回收空间
//将运行完的进程记录在outcome中,以便后续打印
if(outcome == NULL)
{
outcome = k;
foutcome = outcome;
}
else
{
foutcome->next = k;
foutcome = k;
}
//从等待队列中取进程到运行队列中,并更新当前时间
if(yx == NULL&&dd!=NULL)
{
node *y;
y = dd;
dd = dd->next;
y->next = NULL;
yx = y;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min) //更新now
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->start.hour = now.hour;
yx->start.min = now.min;
}
}
//等待队列和运行队列可能不为空
//将等待队列中的结点放入到运行队列中
while(yx!=NULL)
{
node *k;
k = yx;
yx = yx->next;
k->start.hour = now.hour;
k->start.min = now.min;
now.hour = k->start.hour+(k->start.min+k->zx)/60;
now.min = (k->start.min+k->zx)%60;
k->finish.hour = now.hour;
k->finish.min = now.min;
k->zz = k->finish.hour*60+k->finish.min-k->arrive.hour*60-k->arrive.min;
k->zzxs = k->zz*1.0/k->zx;
space += k->size;
if(outcome == NULL)
{
outcome = k;
foutcome = outcome;
}
else
{
foutcome->next = k;
foutcome = k;
}
if(yx == NULL&&dd!=NULL)
{
node *y;
y = dd;
dd = dd->next;
y->next = NULL;
yx = y;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min) //更新now
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->start.hour = now.hour;
yx->start.min = now.min;
}
}
output(outcome);
}
//函数名:HRRF参数:无
void HRRF(){
//函数功能:调用响应比最高者优先算法(HRRF)
printf("\n***********HRRF多道批处理作业调度***********\n");
node *head = in();
node *h,*q;
h = NULL;
q = head;
while(q!=NULL)//对进程按到达时间先后排序
{
node *p = (node *)malloc(sizeof(node));
*p = *q;
p->next = NULL;
if(h == NULL)
{
h = p;
}
else
{
node *a,*apre;
a = h;
while(a!=NULL)
{
if(p->arrive.hour*60+p->arrive.min<a->arrive.hour*60+a->arrive.min)
break;
apre = a;
a = a->next;
}
if(a == h)
{
p->next = h;
h = p;
}
else
{
p->next = a;
apre->next = p;
}
}
q = q->next;
}
//开始HRRF算法
time now;
node *yx,*dd,*ppre,*fdd,*outcome,*foutcome,*p,*pp;
int space,nonow;
now.hour = 0;
now.min = 0;
yx = NULL;
dd = NULL;
outcome = NULL;
space = memory.size;
while(h!=NULL)
{
//每一次大循环都找在自己执行完的时间内并且符合条件的 摘下来
//大循环每次末尾都回收第一个
pp = h;
if(yx == NULL)//操作运行队列 两种情况:一是第一次运行 二是等待队列中没有进程
{
h = h->next;
pp->next = NULL;
yx = pp;
pp = h;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min)//(进程到达时间 > 当前时间 )——>更新当前时间
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->zhuangru.hour = now.hour;
yx->zhuangru.min = now.min;
yx->start.hour = now.hour;
yx->start.min = now.min;
nonow = (yx->start.hour+(yx->start.min+yx->zx)/60)*60+(yx->start.min+yx->zx)%60;//记下运行进程的结束时间,用于计算响应比
space -= yx->size;
}
//寻找满足条件的进程
//对队列按响应比排序(响应比高的在前面) ,得到队列:duilie
node *w,*duilie,*prew,*ww;//w:遍历h duilie:排序后的队列 prew:记录ww的前驱 ww:遍历duilie(找合适的位置插入结点)
w = h;
duilie = NULL;
while(w!=NULL)
{
node *o = (node *)malloc(sizeof(node));
*o = *w;
o->next = NULL;
if(duilie==NULL)
{
duilie = o;
}
else
{
ww = duilie;
while(ww!=NULL)
{
if((nonow-o->arrive.hour*60-o->arrive.min)>0&&(nonow-o->arrive.hour*60-o->arrive.min+o->zx)*1.0/o->zx>(nonow-ww->arrive.hour*60-ww->arrive.min+ww->zx)*1.0/ww->zx)
break;
prew = ww;
ww = ww->next;
}
if(ww==duilie)
{
o->next = duilie;
duilie = o;
}
else
{
o->next = ww;
prew->next = o;
}
}
w = w->next;
}
//在排序后的队列duilie中寻找满足条件的进程
p = duilie;
while(p!=NULL)
{
//在有进程运行的同时,寻找满足条件的进程
//条件是:(1)在进程运行完成之前到达 (2)并且有空间
if(p->arrive.hour*60+p->arrive.min<=yx->start.hour*60+yx->start.min+yx->zx&&space-p->size>=0)
{
space -= p->size;
//删除h上的结点
node *check,*precheck;//摘下
check = h;
while(check!=NULL)
{
if(strcmp(p->name,check->name)==0)
break;
precheck = check;
check = check->next;
}
if(check==h)
{
h = h->next;
}
else
{
precheck->next = check->next;
}
check->next = NULL;
if(dd == NULL)//把摘下的进程放入等待队列
{
dd = check;
fdd = dd;
}
else
{
fdd->next = check;
fdd = check;
}
//修改装入时间
if(now.hour*60+now.min>check->arrive.hour*60+check->arrive.min)
{
check->zhuangru.hour = now.hour;
check->zhuangru.min = now.min;
}
else
{
check->zhuangru.hour = check->arrive.hour;
check->zhuangru.min = check->arrive.min;
}
}
p = p->next;
}
//回收资源(即开始运行进程)
node *k;
k = yx;
yx = yx->next;
k->start.hour = now.hour;
k->start.min = now.min;
now.hour = k->start.hour+(k->start.min+k->zx)/60;
now.min = (k->start.min+k->zx)%60;
k->finish.hour = now.hour;
k->finish.min = now.min;
k->zz = k->finish.hour*60+k->finish.min-k->arrive.hour*60-k->arrive.min;//计算周转时间
k->zzxs = k->zz*1.0/k->zx;//计算周转系数
space += k->size;//回收空间
//将运行完的进程记录在outcome中,以便后续打印
if(outcome == NULL)
{
outcome = k;
foutcome = outcome;
}
else
{
foutcome->next = k;
foutcome = k;
}
//从等待队列中取进程到运行队列中,并更新当前时间
if(yx == NULL&&dd!=NULL)
{
node *y;
y = dd;
dd = dd->next;
y->next = NULL;
yx = y;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min) //更新now
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->start.hour = now.hour;
yx->start.min = now.min;
}
}
//等待队列和运行队列可能不为空
//将等待队列中的结点放入到运行队列中
while(yx!=NULL)
{
node *k;
k = yx;
yx = yx->next;
k->start.hour = now.hour;
k->start.min = now.min;
now.hour = k->start.hour+(k->start.min+k->zx)/60;
now.min = (k->start.min+k->zx)%60;
k->finish.hour = now.hour;
k->finish.min = now.min;
k->zz = k->finish.hour*60+k->finish.min-k->arrive.hour*60-k->arrive.min;
k->zzxs = k->zz*1.0/k->zx;
space += k->size;
if(outcome == NULL)
{
outcome = k;
foutcome = outcome;
}
else
{
foutcome->next = k;
foutcome = k;
}
if(yx == NULL&&dd!=NULL)
{
node *y;
y = dd;
dd = dd->next;
y->next = NULL;
yx = y;
if(yx->arrive.hour*60+yx->arrive.min>now.hour*60+now.min) //更新now
{
now.hour = yx->arrive.hour;
now.min = yx->arrive.min;
}
yx->start.hour = now.hour;
yx->start.min = now.min;
}
}
output(outcome);
}
//函数名:Out参数:无
void Out(){
//函数功能:输出选项菜单
printf("***************多道批处理作业调度***************\n");
printf(" * 1.先来先服务调度算法(FCFS) *\n");
printf(" * 2.最短作业优先算法(SPF) *\n");
printf(" * 3.响应比最高者优先算法(HRRF) *\n");
printf(" * 0.退出 *\n");
printf(" 请输入选项[ ]\b\b");
}
int main()
{
while (1)
{
Out();//给出选项
int c;
scanf("%d", &c);
switch (c){//选择算法
case 1:FCFS();
break;
case 2:SPF();
break;
case 3:HRRF();
break;
default:printf("\n调度结束!");
exit(1);
}
}
return 0;
}
实验结果
实验总结
①新建链表的插入,尾插法是最容易的;
②删除结点的时候没有考虑是头结点;
③在修改结点的属性时,没有实际修改,因为修改后的结点仅仅用来查找;
④没有注意到实际情况,进程还未到达是就被我装入主存中了;
⑤对链表的操作有时会去找空指针的属性,导致程序意外中断;
⑥当从等待队列中取进程时,要判断所取的进程的到达时间是否大于当前时间,如果是则更新当前时间。