实验一 实现单处理机下的进程调度程序

整理整理代码,方便一下学弟。

每年的题目细节可能改,可以按注释自行修改代码。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int INF = 0x7fffffff;

int op;

struct node {
	int pid;//进程号
	int come;//进程到达时间
	int run;//进程运行时间
	int pri;//进程优先级
	int rt;//进程时间片
}
tmp;
int cnt;
struct node que[101010];
bool vis[101010];

int nowp;
struct ANS {
	int id;//运行序号
	int pid;//进程号
	int st;//进程开始运行时间
	int en;//进程结束运行时间
	int pri;//进程优先级
}ans;

node qu[101010];//就绪队列
int he;//就绪队列头部 
int ta;//就绪队列尾部

void print(struct ANS e);//打印处理机所处理进程的信息,信息存储在struct ANS结构中

bool fcfscmp(node a, node b);
//先来先服务算法进程排序规则,先按照到达时间升序,再按照进程号升序排列
bool spfcmp(node a, node b);
//短作业优先算法进程排序规则,先按照到达时间升序,再按照运行时间升序,再按进程号升序排列
bool rrcmp(node a, node b);
//时间片轮转算法进程排序规则,先按照到达时间升序,再按照进程号升序排列
bool pricmp(node a, node b);
//动态优先级算法进程排序规则,先按照进程优先数升序,再按到达时间升序,再按进程号升序排列


void FCFS();//先来先服务调度算法
void SPF_N();//不可剥夺的短作业优先调度算法
void SPF_P();//可剥夺的短作业优先调度算法
void RR();//时间片轮转调度算法
void PRI();//动态优先级调度算法

int main() {
	cnt = 0;
	scanf("%d", &op);//
	int r = 0;
	while (~scanf("%d/%d/%d/%d/%d", &tmp.pid, &tmp.come, &tmp.run, &tmp.pri, &tmp.rt)) {
		que[++cnt] = tmp;
		r++;
	}
	if (cnt == 0)return 0;
	switch (op) {
	case 1:FCFS();break;//先来先服务调度算法
	case 2:SPF_N();break;//不可剥夺的短作业优先调度算法
	case 3:SPF_P();break;//可剥夺的短作业优先调度算法
	case 4:RR();break;//时间片轮转调度算法
	case 5:PRI();break;//动态优先级调度算法
	}
	system("pause");
	return 0;
}
void PRI() {
	int runtime = 0, nowtime = 0;//当前运行时间和进程运行总时间爱你
	memset(vis, 0, sizeof(vis));
	he = 1;ta = 0;
	int t = 0;
	ans.id = 0;
	for (int i = 1;i <= cnt;i++)//计算进程运行总时间
		runtime += que[i].run;
	for (;;) {
		for (int i = 1;i <= cnt;i++) {
			if (vis[i] == 1)continue;
			if (que[i].come <= t) {//将到达的进程加入就绪队列
				qu[++ta] = que[i];
				vis[i] = 1;
			}
		}
		if (ta < he) {//就绪队列为空时,时钟加一,重新查找到达的进程
			t++;
			continue;
		}
		sort(qu + he, qu + ta + 1, pricmp);//将就绪队列中的进程排序
		qu[he].pri += 3;//运行一个时间片的进程优先数加三
		ans.pri = qu[he].pri;
		ans.id++;//运行进程信息
		ans.pid = qu[he].pid;
		ans.st = t;
		t += min(qu[he].rt, qu[he].run);//运行时间为需要运行时间和时间片的较小值
		ans.en = t;
		print(ans);
		nowtime += ans.en - ans.st;
		if (nowtime == runtime)return;//当前运行时间等于需要运行总时间时算法结束
		node np = qu[he++];
		for (int i = 1;i <= cnt;i++) {
			if (vis[i] == 1)continue;
			if (que[i].come<t) {//****将此刻之前的到达的进程都加入队列,为了后面的优先级改变
				qu[++ta] = que[i];
				vis[i] = 1;
			}
		}
		for (int i = he;i <= ta;i++) {//将队列中的进程优先级数加一
			node tmp = qu[i];
			tmp.pri -= 1;//每个队列中的进程优先级数减一
			if (tmp.pri < 0)//优先级数最小为0
				tmp.pri = 0;
			qu[i] = tmp;
		}
		np.run -= (ans.en - ans.st);
		if (np.run != 0)//当前程序没有运行完,需要重新加入就绪队列
			qu[++ta] = np;
	}
}

void RR() {
	memset(vis, 0, sizeof(vis));
	queue<node>q;//就绪队列
	int t = 0;
	int runtime = 0, nowrun = 0;//当前运行时间和进程运行总时间
	sort(que + 1, que + cnt + 1, rrcmp);//排序
	for (int i = 1;i <= cnt;i++) { runtime += que[i].run; }//计算进程运行总时间
	q.push(que[1]);vis[que[1].pid] = 1;//就绪队列中加入第一个进程
	int p = que[1].pid;
	int ip;
	node np = q.front();q.pop();
	ans.id = 1;//第一个答案的信息
	ip = 1;
	t = np.come;
	ans.st = np.come;
	ans.pid = np.pid;
	ans.pri = np.pri;
	int flag1 = 0;
	t += min(np.run, np.rt);//运行时间为时间片和需要运行时间的较小值
							//更改进程运行时间,并增加时钟
	for (;;) {
		for (int i = 1;i <= cnt;i++) {
			if (vis[que[i].pid] == 1 || que[i].pid == p)continue;
			if (que[i].come <= t) {//将到达的进程加入就绪队列,并标志
				q.push(que[i]);
				vis[que[i].pid] = 1;
			}
		}
		if (flag1 == 1) {//当前没有程序运行
			if (q.empty()) {//现在就绪队列为空
				t++;//继续时钟加一
				continue;
			}
			else {//就绪队列不为空
				np = q.front();//取出首个进程运行
				q.pop();p = np.pid;
				ans.id++;//进程的信息
				ans.pid = p;
				ans.st = t;
				ans.pri = np.pri;
				t += min(np.run, np.rt); //更改进程运行时间,并增加时钟
				continue;
			}
		}
		else if (np.run <= np.rt) {//当前有进程运行时,如果需要运行时间小于等于时间片
			vis[p] = 1;
			ans.en = t;
			nowrun += ans.en - ans.st;
			print(ans);//打印答案
			if (nowrun == runtime)return;//如果当前运行时间等于进程运行总时间,算法结束

			if (q.empty()) {//就绪队列为空
				flag1 = 1;//标志没有进程运行
				t++;
				continue;
			}
			flag1 = 0;//标志有进程运行
			np = q.front();
			q.pop();p = np.pid;
			ans.id++;//进程具体信息
			ans.pid = p;
			ans.st = t;
			ans.pri = np.pri;
			t += min(np.run, np.rt);//更改进程运行时间,并增加时钟
			continue;
		}
		else {//当需要运行时间大于时间片,进程不会在这次运行完,还需要重新加入就绪队列
			np.run -= np.rt;
			q.push(np);//重新加入就绪队列
			ans.en = t;
			nowrun += ans.en - ans.st;
			print(ans);
			if (nowrun == runtime)return; //如果当前运行时间等于进程运行总时间,算法结束
			flag1 = 0;//就绪队列不为空
			np = q.front();//取出首个进程运行
			q.pop();p = np.pid;
			ans.id++;//进程运行信息
			ans.pid = p;
			ans.st = t;
			ans.pri = np.pri;
			t += min(np.run, np.rt); //更改进程运行时间,并增加时钟
		}
	}
}

void SPF_P() {
	memset(vis, false, sizeof(vis));
	int t = 0;//时钟t
	int d;
	int rt;
	int p, q;
	int nowrun = 0;//当前程序运行时间
	int runtime = 0;//程序运行总时间
	for (int i = 1;i <= cnt;i++)runtime += que[i].run;
	sort(que + 1, que + 1 + cnt, spfcmp);//进程排序
	int id = 1;
	ans.id = 1;//第一个运行的进程
	ans.st = que[1].come;
	ans.pid = que[1].pid;
	ans.pri = que[1].pri;
	ans.en = ans.st;
	p = 1;q = 2;
	t = que[1].come + 1;
	int flag1 = 0;
	for (;;t++) {//时钟每次加一
		if (flag1 == 0) {//如果处理机正在处理进程,进程的运行时间加一,应该运行时间减一
			ans.en++;que[p].run--;
		}
		while (q <= cnt && que[q].come <= t) { q++; }//将到达的进程加入就绪队列
		if (que[p].run == 0) {//当前正在运行的程序已经运行完
			int mmin = INF;
			for (int i = 1;i < q;i++) {//在就绪队列中查找可以运行的进程
				if (que[i].run == 0)continue;
				if (que[i].run < mmin || (que[i].run == mmin&&que[i].come < que[p].come)) {
					//选择运行时间短,运行时间相同时到达时间早的进程
					mmin = que[i].run;
					p = i;
				}
			}
			nowrun += ans.en - ans.st;
			print(ans);
			if (nowrun == runtime)return;//如果当前运行时间等于进程运行总时间,处理结束
			if (mmin == INF) {//没有找到可以运行的进程,也就是就绪队列为空
				flag1 = 1;//标志没有进程正在进行,处理机空闲
				continue;
			}
			flag1 = 0;//标志处理机在处理进程
			ans.id++;//更新答案数据
			ans.st = t;
			ans.pid = que[p].pid;
			ans.pri = que[p].pri;
			ans.en = ans.st;
		}
		else {
			int mmin = INF;
			int np;
			for (int i = 1;i < q;i++) {//在就绪队列中查找可以运行的进程
				if (que[i].run == 0)continue;
				if (que[i].run < mmin || (que[i].run == mmin&&que[i].come < que[np].come)) {
					//选择运行时间短,运行时间相同时到达时间早的进程
					mmin = que[i].run;
					np = i;
				}
			}
			flag1 = 0; //标志处理机在处理进程
			if (mmin == INF)continue;
			if (que[np].run < que[p].run || (que[np].run == que[p].run&&que[np].come < que[p].come)) {
				//选择运行时间短,运行时间相同时到达时间早的进程
				nowrun += ans.en - ans.st;
				print(ans);
				if (nowrun == runtime)return; // 如果当前运行时间等于进程运行总时间,处理结束
					p = np;
				ans.id++;//更新答案数据
				ans.st = t;
				ans.en = t;
				ans.pid = que[p].pid;
				ans.pri = que[p].pri;
			}
		}
	}

}

void SPF_N() {
	int t = 0;//时钟t
	int p = 1;
	for (int i = 1;i <= cnt;i++) {//每个进程只运行一次,一共运行cnt个进程
		int flag1 = 0;
		while (flag1 == 0) {//当就绪队列中没有进程时,时钟t++,循环等待
			for (int j = 1;j <= cnt;j++) {
				if (que[j].run == 0)continue;//已经运行完成的进程
				if (que[j].come > t)continue;//没有到达的进程
				if (que[j].come <= t&&flag1 == 0) {
					p = j;
					flag1 = 1;
				}
				else if (que[j].come <= t&&flag1 == 1) {
					if ((que[j].run<que[p].run) || (que[j].run == que[p].run&&que[j].pid<que[p].pid)) {
						//运行时间短的进程优先,运行时间相同时,进程号小的优先
						p = j;
					}
				}
			}
			if (flag1 == 0)t++;//就绪队列为空,时钟t++,循环等待
		}
		ans.id = i;//对结果信息赋值
		ans.pid = que[p].pid;
		ans.pri = que[p].pri;
		ans.st = t;
		ans.en = ans.st + que[p].run;
		t = ans.en;
		que[p].run = 0;
		print(ans);//打印结果进程
	}
	return;
}

void FCFS() {
	//将进程按照到达时间升序,进程号升序排列,然后按照排列依次运行各程序
	int t = 0;
	sort(que + 1, que + 1 + cnt, fcfscmp);//进程排序
	for (int i = 1;i <= cnt;i++) {//依次运行各程序
		ans.id = i;ans.pid = que[i].pid;
		ans.st = max(t, que[i].come);
		ans.en = ans.st + que[i].run;
		ans.pri = que[i].pri;
		t = ans.en;
		print(ans);//打印程序的具体运行信息
	}
	return;
}


void print(struct ANS e) {
	printf("%d/%d/%d/%d/%d\n", e.id, e.pid, e.st, e.en, e.pri);
}

bool fcfscmp(node a, node b) {
	if (a.come != b.come)return a.come < b.come;
	return a.pid < b.pid;
}

bool spfcmp(node a, node b) {
	if (a.come != b.come)return a.come < b.come;
	else if (a.run != b.run)return a.run < b.run;
	else return a.pid < b.pid;
}

bool rrcmp(node a, node b) {
	if (a.come != b.come)return a.come < b.come;
	return a.pid < b.pid;
}

bool pricmp(node a, node b) {
	if (a.pri != b.pri)return a.pri < b.pri;
	if (a.come != b.come)return a.come < b.come;
	return a.pid < b.pid;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章