實驗一 實現單處理機下的進程調度程序

整理整理代碼,方便一下學弟。

每年的題目細節可能改,可以按註釋自行修改代碼。

#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;
}


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