操作系统调度算法-短进程优先的调度算法(SPF)c语言实现

目录

一、算法原理

二、算法步骤(两种步骤)

第一种(排序版)

第二种(不排序版)

三、算法时间计算

四、算法代码实现

1.结构体及结构体数组

2.进程位置交换函数

3.找早最提交的进程函数

4.排序算法函数

5.SPF算法函数

第一种(排序版):

第二种(不排序版):

6.信息展示函数

7.main函数

五、实现效果


一、算法原理

        短进程优先调度算法的核心思想是:执行时间较短的进程会被优先调度执行,以减少平均等待时间和提高系统的响应速度。每个进程被分配一个执行时间,通常用一个整数来表示,执行时间越短表示优先级越高。当系统中有多个就绪进程时,调度程序会选择执行时间最短的进程进行执行。

二、算法步骤(两种步骤)

第一种(排序版)

        首先对进程按照运行时间进行排序。
        从排好序开始位置开始往后找,找已经到了的进程,如果找到了就交换位置并执行。如果没有找到,就表示所以进程没有到达,那就从开始位置找一个最早提交时间的进程并执行。

第二种(不排序版)

        同时找在当前时间已经到了又是最小运行时间的进程,如果找到了,交换位置并执行,如果没有找到,就表示所以进程没有到达,那就从开始位置找一个最早提交时间的进程并执行。

三、算法时间计算

开始时间 =如果提交时间早于等于上一个完成时间,则开始时间为上一个完成时间;(第一个作业的开始时间=提交时间,也就是下标为0)

完成时间 =开始时间+运行时间 ;

周转时间 = 完成时间- 提交时间 ;

带权周转时间 = 周转时间 / 运行时间 ;

平均周转时间 = 周转时间总和 / 作业个数

平均带权周转时间 = 带权周转时间总和/ 作业个数

四、算法代码实现

1.结构体及结构体数组

#define MAX 4
struct PCB
{
	int id;				//进程号 
	double submittime;       //提交时间 
	double runtime;           //运行时间 
	double starttime;         //开始时间 
	double finishtime;        //完成时间 
	double cycletime;        //周转时间 
	double qtt;        //带权周转时间 
};
//struct JCB jcb[10];
struct PCB pcb[MAX] = {
	{1, 1.0, 2.0},
	{2, 2.0, 1.0},
	{3, 0.0, 2.0},
	{4, 6.0, 1.0}
};

2.进程位置交换函数

/// <summary>
/// 进程位置交换
/// </summary>
/// <param name="i"></位置i>
/// <param name="tmpNum"></位置tmpNum>
void swap_p(int i, int tmpNum)
{
	struct PCB tmp = pcb[tmpNum];
	pcb[tmpNum] = pcb[i];
	pcb[i] = tmp;
}

3.找早最提交的进程函数

/// <summary>
/// 在n个进程中,从j开始找到一个最早提交时间的进程
/// </summary>
/// <param name="n"></进程个数>
/// <param name="j"></开始位置>
void getMinSubmittime(int n, int j)
{
	int tmpNum = j;
	for (int i = j + 1; i < n - 1; i++)
	{
		struct PCB tmp = pcb[tmpNum];
		if (pcb[i].submittime < tmp.submittime)
		{
			tmpNum = i;
		}
	}
	swap_p(j,tmpNum);
}

4.排序算法函数

/// <summary>
/// 在n个进程中,从=i开始直接插入排序按作业运行时间升序排序
/// </summary>
/// <param name="n"></进程个数>
/// <param name="i"></开始位置>
void InsertSort(int n, int i)
{
	int start = i;
	for (; i < n - 1; i++)
	{
		int end = i;
		struct PCB tmp = pcb[end + 1];
		while (end >= start && pcb[end].runtime > tmp.runtime)
		{
			pcb[end + 1] = pcb[end];
			end--;
		}
		pcb[end + 1] = tmp;
	}
}

5.SPF算法函数

第一种(排序版):

void SPF(int num)
{
	getMinSubmittime(num, 0);//从0开始找到一个最早提交时间的进程,也就是第一个到了执行的进程
	int i = 0;
	pcb[i].starttime = pcb[i].submittime;
	pcb[i].finishtime = pcb[i].starttime + pcb[i].runtime;
	pcb[i].cycletime = pcb[i].finishtime - pcb[i].submittime;
	pcb[i].qtt = pcb[i].cycletime / pcb[i].runtime;
	for (i = 1; i < num; i++)
	{
		InsertSort(num, i);//从=i开始直接插入排序按作业运行时间升序排序
		int flagnum = -1;
		//从排好序i位置开始往后找,找已经到了的进程
		for (int j = i; j < num; j++) {
			if (pcb[j].submittime <= pcb[i - 1].finishtime)
			{
				flagnum = j;
				break;
			}
		}
		if (flagnum != -1)//如果找到了就叫互换
		{
			swap_p(i, flagnum);
		}
		else//如果没有找到,就表示所以进程没有到达,那就从j开始找一个最早提交时间的进程
		{
			getMinSubmittime(num, i);
		}
		//计算
		if (pcb[i].submittime <= pcb[i - 1].finishtime)
		{
			pcb[i].starttime = pcb[i - 1].finishtime;
		}
		else
		{
			pcb[i].starttime = pcb[i].submittime;
		}
		pcb[i].finishtime = pcb[i].starttime + pcb[i].runtime;
		pcb[i].cycletime = pcb[i].finishtime - pcb[i].submittime;
		pcb[i].qtt = pcb[i].cycletime / pcb[i].runtime;
	}
}

第二种(不排序版):

/// <summary>
///  同时找在当前时间已经到了又是最小运行时间的进程
/// </summary>
/// <param name="n"></进程个数>
/// <param name="j"></开始位置>
/// <param name="nowtime"></当前时间>
void getMinSubtime_runtime(int n, int j, int nowtime)
{	
	int tmpNum = j;
	double tmprun = INT_MAX;
	int flag = -1;
	for (int i = j; i < n; i++)
	{
		struct PCB tmp = pcb[tmpNum];
		//找已经到了又是最小运行时间
		if (pcb[i].submittime <= nowtime && pcb[i].runtime <= tmprun)
		{			
			tmpNum = i;
			flag = 1;
			tmprun = pcb[i].runtime;//更新最小运行时间
		}
	}
	//判断有没有找到,不能用if (tmpNum !=j),因为可能符合条件的就是j
	if (flag == 1)
	{
		swap_p(j, tmpNum);
	}
	else {
		getMinSubmittime(n, j);
	}
}
void SPF2(int num)
{
	getMinSubmittime(num, 0);//从0开始找到一个最早提交时间的进程,也就是第一个到了执行的进程
	int i = 0;
	pcb[i].starttime = pcb[i].submittime;
	pcb[i].finishtime = pcb[i].starttime + pcb[i].runtime;
	pcb[i].cycletime = pcb[i].finishtime - pcb[i].submittime;
	pcb[i].qtt = pcb[i].cycletime / pcb[i].runtime;
	for (i = 1; i < num; i++)
	{
		int newtime = pcb[i - 1].finishtime;//当前时间就是上一个的完成时间
		getMinSubtime_runtime(num, i, newtime);
		//计算
		if (pcb[i].submittime <= pcb[i - 1].finishtime)
		{
			pcb[i].starttime = pcb[i - 1].finishtime;
		}
		else
		{
			pcb[i].starttime = pcb[i].submittime;
		}
		pcb[i].finishtime = pcb[i].starttime + pcb[i].runtime;
		pcb[i].cycletime = pcb[i].finishtime - pcb[i].submittime;
		pcb[i].qtt = pcb[i].cycletime / pcb[i].runtime;
	}
}

6.信息展示函数

void showInfo(int num)
{
	double acycletime = 0.0;
	double aqtt = 0.0;
	printf("进程号 \t提交时间\t运行时间\t开始时间\t完成时间\t周转时间\t带权周转时间\n");
	for (int i = 0; i < num; i++)
	{
		printf("%d\t  %0.1lf\t\t   %0.1lf\t\t   %0.1lf\t\t   %0.1lf\t\t   %0.1lf\t\t   %0.1lf\n", pcb[i].id, pcb[i].submittime, pcb[i].runtime, pcb[i].starttime, pcb[i].finishtime, pcb[i].cycletime, pcb[i].qtt);
		acycletime += pcb[i].cycletime;
		aqtt += pcb[i].qtt;
	}
	printf("平均周转时间=%0.1lf\n", acycletime / num);
	printf("平均带权周转时间=%0.1lf\n", aqtt / num);
}

7.main函数

int main()
{
	int num = MAX;
	//SPF1(num);
	SPF2(num);
	showInfo(num);
	return 0;
}

五、实现效果

#include //定义一个结构体 struct sjf{ char name[10]; //进程名 float arrivetime; //到达时间 float servicetime;//服务时间 float starttime; //开始时间 float finishtime;//完成时间 float zztime;//周转时间 float dqzztime;//带权周转 }; //定义一个结构体数组 sjf a[100]; //定义一个输入函数 void input(sjf *p,int N) { int i; printf("intput the process's name & arrivetime & servicetime:\nfor exmple: a 0 100\n"); for(i=0;i<=N-1;i++) { printf("input the %dth process's information:\n",i+1); scanf("%s%f%f",&p[i].name,&p[i].arrivetime,&p[i].servicetime); } } //定义一个输出函数 void Print(sjf *p,float arrivetime,float servicetime,float starttime,float finishtime,float zztime,float dqzztime,int N) { int k; printf("run order:");//执行顺序 printf("%s",p[0].name); for(k=1;k%s",p[k].name); } printf("\nthe process's information:\n"); printf("\nname\tarrive\tservice\tstart\tfinish\tzz\tdqzz\n"); for(k=0;k<=N-1;k++) { printf("%s\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t\n",p[k].name,p[k].arrivetime,p[k].servicetime,p[k].starttime,p[k].finishtime,p[k].zztime,p[k].dqzztime); } } //按到达时间排序 void sort(sjf *p,int N) { for(int i=0;i<=N-1;i++) for(int j=0;j<=i;j++) if(p[i].arrivetime<p[j].arrivetime) { sjf temp; temp=p[i]; p[i]=p[j]; p[j]=temp; } } //运行阶段 void deal(sjf *p, float arrivetime,float servicetime,float starttime,float finishtime,float &zztime,float &dqzztime,int N) { int k; for(k=0;k=p[k].arrivetime) { p[k].starttime=p[k-1].finishtime;} else { p[k].starttime =p[k].arrivetime;} p[k].finishtime=p[k].starttime+p[k].servicetime; } } for(k=0;k<=N-1;k++) { p[k].zztime=p[k].finishtime-p[k].arrivetime;//周转时间=完成时间-到达时间 p[k].dqzztime=p[k].zzti
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值