关于 作业调度算法 (FCSF)的学习笔记
学习作业调度算法。
作业调度算法研究的是对于多个作业的时候,找寻最优解的方法,即如何使多项工作能有条理的完成
FCSF算法
FCSF算法即为First Come Serve First(先来先服务。
即根据不同作业到来的时间进行完成,不考虑完成作业的优先性和重要性,作业完成所需要的时间长短问题,每个作业的周转时间,或者是效率问题。同时当遇到开始时间相同的情况,以输入的顺序进行完成。
因此,FCSF算法是作业调度算法中书写难度&理解难度最低的,同时也是效率比较低。
输入
首先输入所需要完成的作业数量。
再分别输入每个作业的开始时间&运行时间
输出
输出每项作业的开始时间,运行时间,开始时间,结束时间,周转时间,带权周转时间
最后输出平均周转时间,平均带权周转时间
思路
1.在循环过程中,找到最早的程序到达时间。
具体代码
int GetNextTask(int now)
{
int minx=100000,index=-1;
for(int i=1; i<=tasknum; i++)
if(!arrayTask[i].flag&&arrayTask[i].arrive<=now&&arrayTask[i].arrive<minx)
{
minx=arrayTask[i].arrive;//更新最早到达时间
index=i;//更新最早更新的项目代码
}
return index;
}
2.找到到达时间最早的作业之后,计算该作业的各项数据。
void RunTask(int n)
{
arrayTask[n].start = nowtime;//更新任务开始时间
arrayTask[n].endtime = nowtime + arrayTask[n].service;//计算任务结束时间
arrayTask[n].runtime = arrayTask[n].endtime - arrayTask[n].arrive;//计算周转时间
avgruntime += arrayTask[n].runtime;//记录总的周转时间,用于计算平均周转时间
arrayTask[n].dqzztime = arrayTask[n].runtime / arrayTask[n].service;//计算加权周转时间
avgdqzztime += arrayTask[n].dqzztime;//记录总的带权周转时间,用于计算平均带权周转时间
arrayTask[n].flag=1;//标记该任务已经完成
}
3.依次输出每个作业的各项数据
总代码
#include<iostream>
#include<string>
#include<fstream>
#include<iomanip>
using namespace std;
const int MAXN = 100000;
int tasknum;//作业数量
int nowtime; //从第一个到达的作业时间开始
double avgruntime; //平均周转时间
double avgdqzztime; //平均带权周转时间
struct StruTask
{
int id; //序号
int flag=0;
int arrive; //到达时间(输入)
int service; //服务时间(输入)
int start; //开始时间(设置)
int endtime; //结束时间(设置)
int runtime; //周转时间:endtime - arrive
double dqzztime; //带权周转时间runtime/service
}arrayTask[MAXN];
void GetTask()
{
cout<<"请输入任务数:"<<endl;
cin>>tasknum;
if(tasknum <= 0) return;
for(int i = 1; i <= tasknum; ++i)
{
cout<<"请输入第"<<i<<"个任务的到达时间和服务时间: ";
arrayTask[i].id = i;
cin>>arrayTask[i].arrive;
cin>>arrayTask[i].service;
}
}
int GetNextTask(int now)
{
int minx=100000,index=-1;
for(int i=1; i<=tasknum; i++)
if(!arrayTask[i].flag&&arrayTask[i].arrive<=now&&arrayTask[i].arrive<minx)
{
minx=arrayTask[i].arrive;
index=i;
}
return index;
}
void RunTask(int n)
{
arrayTask[n].start = nowtime;
arrayTask[n].endtime = nowtime + arrayTask[n].service;
arrayTask[n].runtime = arrayTask[n].endtime - arrayTask[n].arrive;
avgruntime += arrayTask[n].runtime;
arrayTask[n].dqzztime = arrayTask[n].runtime / arrayTask[n].service;
avgdqzztime += arrayTask[n].dqzztime;
arrayTask[n].flag=1;
}
void PrintResult(int n)
{
cout<<" 序号: "<<arrayTask[n].id
<<" 到达时间: "<<arrayTask[n].arrive<<" 服务时间: "<<arrayTask[n].service;
cout<<" 开始时间: "<<arrayTask[n].start<<" 结束时间: "<<arrayTask[n].endtime;
cout<<" 周转时间: "<<arrayTask[n].runtime<<" 带权周转时间: "<<arrayTask[n].dqzztime<<endl;
}
int main()
{
GetTask();
nowtime = 0;
avgruntime = 0;
avgdqzztime = 0;
for(int i = 1; i <= tasknum; ++i)
{
int id = GetNextTask(nowtime);
RunTask(id);
PrintResult(id);
nowtime=arrayTask[id].endtime;
}
avgruntime /= tasknum;
avgdqzztime /= tasknum;
cout<<" 平均周转时间: "<<avgruntime<<" 平均带权周转时间: "<<avgdqzztime<<endl;
return 0;
}
补充
1.周转时间=运行时间+等待时间
2.带权周转时间=运行时间/周转时间
因此带权周转时间越接近1,效率越佳。
3.代码输出的顺序等同于作业完成顺序,如果想要以输入顺序需要再写一个循环程序。即把PrintResult函数放在循环之外,在使用一次for循环,即可按输入顺序输出
再补
C语言重写FCSF算法
#include <stdio.h>
#define MAXN 100000
struct StruTask
{
int id; // 序号
int flag; // 标记是否已执行
int arrive; // 到达时间(输入)
int service; // 服务时间(输入)
int start; // 开始时间(设置)
int endtime; // 结束时间(设置)
int runtime; // 周转时间: endtime - arrive
double dqzztime; // 带权周转时间: runtime / service
};
int tasknum; // 作业数量
int nowtime; // 从第一个到达的作业时间开始
double avgruntime; // 平均周转时间
double avgdqzztime; // 平均带权周转时间
struct StruTask arrayTask[MAXN];
void GetTask()
{
printf("请输入任务数:\n");
scanf("%d", &tasknum);
if (tasknum <= 0)
return;
for (int i = 1; i <= tasknum; ++i)
{
printf("请输入第%d个任务的到达时间和服务时间: ", i);
arrayTask[i].id = i;
scanf("%d %d", &arrayTask[i].arrive, &arrayTask[i].service);
}
}
int GetNextTask(int now)
{
int minx = 100000;
int index = -1;
for (int i = 1; i <= tasknum; i++)
{
if (!arrayTask[i].flag && arrayTask[i].arrive <= now && arrayTask[i].arrive < minx)
{
minx = arrayTask[i].arrive;
index = i;
}
}
return index;
}
void RunTask(int n)
{
arrayTask[n].start = nowtime;
arrayTask[n].endtime = nowtime + arrayTask[n].service;
arrayTask[n].runtime = arrayTask[n].endtime - arrayTask[n].arrive;
avgruntime += arrayTask[n].runtime;
arrayTask[n].dqzztime = (double)arrayTask[n].runtime / arrayTask[n].service;
avgdqzztime += arrayTask[n].dqzztime;
arrayTask[n].flag = 1;
}
void PrintResult(int n)
{
printf(" 序号: %d 到达时间: %d 服务时间: %d", arrayTask[n].id, arrayTask[n].arrive, arrayTask[n].service);
printf(" 开始时间: %d 结束时间: %d", arrayTask[n].start, arrayTask[n].endtime);
printf(" 周转时间: %d 带权周转时间: %.2f\n", arrayTask[n].runtime, arrayTask[n].dqzztime);
}
int main()
{
GetTask();
nowtime = 0;
avgruntime = 0;
avgdqzztime = 0;
for (int i = 1; i <= tasknum; ++i)
{
int id = GetNextTask(nowtime);
RunTask(id);
PrintResult(id);
nowtime = arrayTask[id].endtime;
}
avgruntime /= tasknum;
avgdqzztime /= tasknum;
printf(" 平均周转时间: %.2f 平均带权周转时间: %.2f\n", avgruntime, avgdqzztime);
return 0;
}