操作系统——优先权算法c++实现

news2024/11/26 20:38:16

变量描述

测试数据

5
A 0 4 4
B 1 3 2
C 2 5 3
D 3 2 5
E 4 4 1

先来先服务算法

简述

该算法实现非常简单就是对到达时间排个序,然后依次进行即可,对结构体的sort进行了重载

代码

void FCFS() {//先来先服务算法
	std::cout<<"\n\t\t\t\t\t先来先服务算法\n\n";
	double sum_cir_time=0;//总的周转时间
	double sum_pre_cir_time=0;//总的带权周转时间
	std::sort(work+1, work +1+ N,cmp1);//来的时间排序

	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	for (int i = 1; i <= N; i++) {
		work[i].start_time = work[i - 1].finish_time;
		work[i].finish_time = work[i].start_time + work[i].need_time;
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id<<"\t"<<work[i].reach_time <<"\t\t"<<work[i].start_time <<"\t\t"<<
			work[i].need_time <<"\t\t"<<work[i].finish_time <<"\t\t"<<work[i].cir_time<<
			"\t\t"<<work[i].pre_cir_time<<"\n";
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time*1.0/N << "\n";
}

短进程优先

简述

需要注意的是不是直接按照进程时间为关键字直接排序,而是对当前时刻的最短进程

例如下面示例

A 1 5
B 2 1

时间上b最短,但是a先来的,所以b要执行,就必须等a执行完毕,实现方式进行枚举,然后每次把当前时刻的进程较短的放入优先队列,使用的是优先队列的小根堆。

代码

void SPJF() {//短进程优先
	std::cout << "\n\t\t\t\t\t短进程优先服务算法\n\n";
	double sum_cir_time = 0;//总的周转时间
	int now_time=0,new_job=0;
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	//把开始时间小于目前时间的都丢到优先队列中
	std::priority_queue<std::pair<int,int>,std::vector<std::pair<int,int> >,std::greater<std::pair<int,int> > >q;
	std::queue<int>order_q;//用于获取编号的
	int ok = 0;//进程结束
	while (ok < N) {
		for (int i = 1; i <= N; i++) {
			if (!work[i].isvisited) {
				if (work[i].reach_time <= now_time) {//把小于当前时间已经到达的进程排序
					work[i].isvisited = 1;
					q.push({ work[i].need_time,work[i].kth});
				}
				else {
					break;//说明后面的进程是,谁先来设服务
				}
			}
		}
		if (q.empty()) {//队列为空说明应该执行先来先服务,当前时刻最短
			for (int i = 1; i <= N; i++) {
				if (!work[i].isvisited) {
					work[i].isvisited = 1;
					new_job = work[i].kth;//获取进程编号
					break;
				}
			}
		}
		else {
			new_job = q.top().second;
			q.pop();
		}
		order_q.push(new_job);
		ok++;
		work[new_job].start_time = std::max(now_time,work[new_job].reach_time);
		now_time=work[new_job].finish_time = work[new_job].start_time + work[new_job].need_time;
		work[new_job].cir_time = work[new_job].finish_time - work[new_job].reach_time;
		sum_cir_time += work[new_job].cir_time;
		work[new_job].pre_cir_time = work[new_job].cir_time * 1.0 / work[new_job].need_time;
		sum_pre_cir_time += work[new_job].pre_cir_time;
	}

	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	while (!order_q.empty()) {
		int i = order_q.front(); order_q.pop();
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";
	
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" <<
		sum_pre_cir_time * 1.0 / N << "\n";
}

优先权算法

(1)非抢占式

        非抢占式就跟短进程实现方式一样,一样使用优先队列,关键字按照优先权大小进行排序即可,每次把当前时刻,有先权比目前更大的丢到优先队列中

代码

void HPF() {
	
	std::cout << "\n\t\t\t\t\t优先权算法(数字小优先)\n\n";
	double sum_cir_time = 0;//总的周转时间
	int now_time=0,new_job=0;
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	//把开始时间小于目前时间的都丢到优先队列中
	
	std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int> >, std::greater<std::pair<int, int> > >q;

	std::queue<int>order_q;//用于获取编号的
	int ok = 0;//进程结束
	while (ok < N) {
		for (int i = 1; i <= N; i++) {
			if (!work[i].isvisited) {
				if (work[i].reach_time <= now_time) {//把小于当前时间已经到达的进程排序
					work[i].isvisited = 1;
					q.push({ work[i].pre,work[i].kth});
				}
				else {
					break;//说明后面的进程是,谁先来设服务
				}
			}
		}
		if (q.empty()) {//队列为空说明应该执行先来先服务,当前时刻最短
			for (int i = 1; i <= N; i++) {
				if (!work[i].isvisited) {
					work[i].isvisited = 1;
					new_job = work[i].kth;//获取进程编号
					break;
				}
			}
		}
		else {
			new_job = q.top().second;
			q.pop();
		}
		order_q.push(new_job);
		ok++;
		work[new_job].start_time = std::max(now_time,work[new_job].reach_time);
		now_time=work[new_job].finish_time = work[new_job].start_time + work[new_job].need_time;
		work[new_job].cir_time = work[new_job].finish_time - work[new_job].reach_time;
		sum_cir_time += work[new_job].cir_time;
		work[new_job].pre_cir_time = work[new_job].cir_time * 1.0 / work[new_job].need_time;
		sum_pre_cir_time += work[new_job].pre_cir_time;
	}

	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t优先权  \t结束时间\t周转时间\t带权周转时间\n";
	while (!order_q.empty()) {
		int i = order_q.front(); order_q.pop();
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t"<<work[i].pre<<"\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";

	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";
}

(2)抢占式

这个比较麻烦,我的思路就是记录下当前时刻的时间,然后循环寻找到达时间小于当前时间的小的并且优先级别较大的,然后比较找到的id是不是目前执行的,如果不是,说明目前的进程会被打断,然后找出从当前时刻到他理想结束时刻的时间(只是理想,不一定会到达)在这个理想时间以内,如果这个时间内有进程来了,并且该进程的优先级更高,说明是目前需要被打段的,然后目前这个进程运行到的时间就是新进程到达的时间,如果没有优先级更高的化就把自己执行完毕

代码

void QHPF(){//优先权抢占式
	std::cout << "\n\t\t\t\t\t优先权抢占算法\n\n";
	double sum_cir_time = 0;//总的周转时间
	
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	std::queue<int>order_q;
	int pre = 1e5;//记录实时的pre
	int ok = 0,now_time=0,now_id=0,lst_id=0;//当前时间,当前编号,上一次的编号
	while (ok < N) {
		pre = 1e5;
		for (int i = 1; i <= N; i++) {
			if (work[i].reach_time <= now_time) {//当前程序可以执行
				if (pre>work[i].pre&&!work[i].isvisited) {//更换优先级更高的
					pre = work[i].pre;
					now_id = work[i].kth;//当前要运行的程序
				}
			}
		}
		
		//std::cout << pre << " " << now_id << "\n";
		if (work[now_id].run_time == 0) {
				work[now_id].start_time = now_time;//该进程开始时在这时候介入
		}
		//std::cout << now_time << "\n";

		if (now_id != lst_id) {//还有进程可以执行
			int tmp_pre = pre;
			int tmp_id=now_id;
			for (int i = 1; i <= N; i++) {//从当前时刻到该作业结束,中间由优先级更高的插入
				if (now_time + work[now_id].need_time - work[now_id].run_time >= work[i].reach
					&& tmp_id != work[i].kth&&!work[i].isvisited&&tmp_pre>work[i].pre) {
					tmp_id = work[i].kth;
					tmp_pre = work[i].pre;
					break;
				}
			}
			

			if (tmp_pre != pre) {//优先级更高的插入
				
				work[now_id].run_time += work[tmp_id].reach_time-now_time;
				
				now_time = work[tmp_id].reach_time;//更新为新进程的到达时间
				lst_id = now_id;
				if (work[now_id].run_time == work[now_id].need_time) {
					work[now_id].finish_time = now_time;
					order_q.push(now_id);
					work[now_id].isvisited = 1;
					ok++;
					continue;
				}
				std::cout << "**执行" << now_id << "被" << tmp_id << "打断!  还剩" << work[now_id].need_time - work[now_id].run_time << "未执行\n";
				
			}
			else {
				lst_id = now_id;//没有优先级更高的插入
				order_q.push(now_id);
				now_time += work[now_id].need_time - work[now_id].run_time;
				work[now_id].finish_time = now_time;
				work[now_id].isvisited = 1;
				ok++;
			}
			//std::cout << now_id << "   " << tmp_id << "  " << pre<<"  "<<tmp_pre <<"  "<<now_time<<"\n";
			

		}
		else {
			now_time++;
		}
	}
	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t优先权  \t结束时间\t周转时间\t带权周转时间\n";
	while (!order_q.empty()) {
		int i = order_q.front(); order_q.pop();
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].pre << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";

	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";

}

时间片轮转

(1)老进程优先

        实现过程使用到了vector和一个队列,其类型为node(即存储各种时间信息),只用一个队列的话就会出现了插队的问题,实现为每次取出vector的头部,然后看他的到达时间是否小于当前时间,小于的话就可以放入队列,然后每次时间增加的时候,就遍历vector数组,如果当前有进程的到达时间小于当前时刻就把该进程塞到队列中,由于是老进程优先,所以需要先把对头放入队尾,再执行上述新进程操作。

代码

void OLD_RR() {//时间片轮转老进程优先
	std::cout << "\n\t\t\t\t\t时间片轮转算法(老进程优先)\n\n";
	double sum_cir_time = 0;//总的周转时间
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	std::queue<node>q;//用于进程
	std::vector<node>v;//存放每一个进程的就绪
	for (int i = 1; i <= N; i++)
		v.push_back(work[i]);//放入队列中
	q.push(*v.begin());
	int now_time = (*v.begin()).reach_time;
	work[(*v.begin()).kth].start_time = now_time;
	v.erase(v.begin());
	int ok = 0;
	while (q.size() || v.size()) {
		while (v.size() && (*v.begin()).reach_time <= now_time) {
			q.push(*v.begin());
			v.erase(v.begin());
		}
		//std::cout << now_time << "\n";
		if (q.front().run_time < q.front().need_time) {//时间片还未用完加入队尾
			std::cout << q.front().id << " ";
			int t = q.front().kth;
			//std::cout << t << "\n";
			now_time++;
			if (work[t].run_time == 0)
				work[t].start_time = now_time;
			work[t].run_time++;
			//std::cout << work[t].run_time <<"  "<<now_time<< "\n";
			if (work[t].run_time == work[t].need_time) {
				work[t].finish_time = now_time;
			}
			
			q.front().run_time++;
			
			q.push(q.front());
			q.pop();
			while (v.size() && (*v.begin()).reach_time <= now_time) {//有新作业到达,加入队列
				q.push(*v.begin());
				v.erase(v.begin());
			}
		}
		else {
			q.pop();
		}
	}
	work[1].start_time = work[1].reach_time;
	std::cout << "\n进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	for (int i = 1; i <= N; i++) {
		//work[i].finish_time = work[i].start_time + work[i].need_time;
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";

}

(2)新进程优先

       跟上述一样实现差不多,主要改动是,上述是时间不变然后塞到队列,现在由于是新进程优先,所以时间得跟着变化,由于是储存到队列中还得取出来,所以不能真正的改变,需要用一个临时变量来进行时间增加加新进程

代码

void NEW_RR() {
	std::cout << "\n\t\t\t\t\t时间片轮转算法(新进程优先)\n\n";
	double sum_cir_time = 0;//总的周转时间
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	std::queue<node>q;//用于进程
	std::vector<node>v;//存放每一个进程的就绪
	for (int i = 1; i <= N; i++)
		v.push_back(work[i]);//放入队列中
	q.push(*v.begin());
	int now_time = (*v.begin()).reach_time;
	work[(*v.begin()).kth].start_time = now_time;
	v.erase(v.begin());
	int ok = 0;
	while (q.size() || v.size()) {
		while (v.size() && (*v.begin()).reach_time <= now_time) {
			q.push(*v.begin());
			v.erase(v.begin());
		}
		//std::cout << now_time << "\n";
		if (q.front().run_time < q.front().need_time) {//时间片还未用完加入队尾
			std::cout << q.front().id << " ";
			int t = q.front().kth;
			//std::cout << t << "\n";
			now_time++;
			if (work[t].run_time == 0)
				work[t].start_time = now_time;
			work[t].run_time++;
			//std::cout << work[t].run_time << "  " << now_time << "\n";
			if (work[t].run_time == work[t].need_time) {
				work[t].finish_time = now_time;
			}

			q.front().run_time++;
			int x = now_time;
			for (;; x++) {
				int f = 0;
				while (v.size() && (*v.begin()).reach_time <= x) {//有新作业到达,加入队列
					q.push(*v.begin());
					v.erase(v.begin());
					f=1;
				}
				if (!f) {
					break;
				}
			}
		
			q.push(q.front());
			q.pop();
		}
		else {
			q.pop();
		}
	}
	work[1].start_time = work[1].reach_time;
	std::cout << "\n进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	for (int i = 1; i <= N; i++) {
		//work[i].finish_time = work[i].start_time + work[i].need_time;
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";

}

完整代码

#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
const int MAX_N=10;
int N;//最大作业数量
struct node {
	char id;//编号
	int kth;//第几个,标识符
	int reach_time;//到达时间
	int need_time;//需要时间
	int wait_time;//等待时间
	int start_time;//开始时间
	int cir_time;//周转时间
	double pre_cir_time;//带权周转时间
	int run_time;//作业执行时间,执行抢占
	int pre;//优先权
	double reply_rate;//响应比
	bool isvisited;//是否进行过这个作业
	int finish_time;//完成时间
	bool reach;//是否到达
}work[MAX_N];


bool cmp1(node &a,node &b) {//先来先服务
	return a.reach_time < b.reach_time;
}

bool cmp2(node& a, node& b) {//数字小的优先权大
	return a.pre < b.pre;
}

bool cmp3(node& a, node& b) {
	return a.pre > b.pre;
}

void ouputinit() {
	std::cout << "进程名\t 到达时间\t服务时间\t优先权\n";
	for (int i = 1; i <= N; i++) {
		std::cout << work[i].id <<"\t  "<< work[i].reach_time << "  \t\t" << work[i].need_time << "\t\t  " << work[i].pre << "\n";
	}
}

void input() {
	std::cout << "请输入进程的数量:\n";
	std::cin >> N;
	std::cout << "请输入各作业的进程名,到达时间,服务时间以及优先权:\n";
	for (int i = 1; i <= N; i++) {
		work[i].kth = i;
		std::cin >> work[i].id >> work[i].reach_time >> work[i].need_time >> work[i].pre;
	}
}

void init() {
	for (int i = 0; i <= N; i++) {
		work[i].id = ' ';
		work[i].reach_time = 0;
		work[i].need_time = 0;
		work[i].wait_time = 0;
		work[i].start_time = 0;
		work[i].cir_time = 0;
		work[i].pre_cir_time = 0;
		work[i].run_time = 0;
		work[i].pre = 0;
		work[i].reply_rate = 0;
		work[i].isvisited = 0;
		work[i].finish_time = 0;
		work[i].reach = 0;
	}
}

void FCFS() {//先来先服务算法
	std::cout<<"\n\t\t\t\t\t先来先服务算法\n\n";
	double sum_cir_time=0;//总的周转时间
	double sum_pre_cir_time=0;//总的带权周转时间
	std::sort(work+1, work +1+ N,cmp1);//来的时间排序

	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	for (int i = 1; i <= N; i++) {
		work[i].start_time = work[i - 1].finish_time;
		work[i].finish_time = work[i].start_time + work[i].need_time;
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id<<"\t"<<work[i].reach_time <<"\t\t"<<work[i].start_time <<"\t\t"<<
			work[i].need_time <<"\t\t"<<work[i].finish_time <<"\t\t"<<work[i].cir_time<<
			"\t\t"<<work[i].pre_cir_time<<"\n";
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time*1.0/N << "\n";
}


void SPJF() {//短进程优先
	std::cout << "\n\t\t\t\t\t短进程优先服务算法\n\n";
	double sum_cir_time = 0;//总的周转时间
	int now_time=0,new_job=0;
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	//把开始时间小于目前时间的都丢到优先队列中
	std::priority_queue<std::pair<int,int>,std::vector<std::pair<int,int> >,std::greater<std::pair<int,int> > >q;
	std::queue<int>order_q;//用于获取编号的
	int ok = 0;//进程结束
	while (ok < N) {
		for (int i = 1; i <= N; i++) {
			if (!work[i].isvisited) {
				if (work[i].reach_time <= now_time) {//把小于当前时间已经到达的进程排序
					work[i].isvisited = 1;
					q.push({ work[i].need_time,work[i].kth});
				}
				else {
					break;//说明后面的进程是,谁先来设服务
				}
			}
		}
		if (q.empty()) {//队列为空说明应该执行先来先服务,当前时刻最短
			for (int i = 1; i <= N; i++) {
				if (!work[i].isvisited) {
					work[i].isvisited = 1;
					new_job = work[i].kth;//获取进程编号
					break;
				}
			}
		}
		else {
			new_job = q.top().second;
			q.pop();
		}
		order_q.push(new_job);
		ok++;
		work[new_job].start_time = std::max(now_time,work[new_job].reach_time);
		now_time=work[new_job].finish_time = work[new_job].start_time + work[new_job].need_time;
		work[new_job].cir_time = work[new_job].finish_time - work[new_job].reach_time;
		sum_cir_time += work[new_job].cir_time;
		work[new_job].pre_cir_time = work[new_job].cir_time * 1.0 / work[new_job].need_time;
		sum_pre_cir_time += work[new_job].pre_cir_time;
	}

	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	while (!order_q.empty()) {
		int i = order_q.front(); order_q.pop();
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";
	
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" <<
		sum_pre_cir_time * 1.0 / N << "\n";
}

void HPF() {
	
	std::cout << "\n\t\t\t\t\t优先权算法(数字小优先)\n\n";
	double sum_cir_time = 0;//总的周转时间
	int now_time=0,new_job=0;
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	//把开始时间小于目前时间的都丢到优先队列中
	
	std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int> >, std::greater<std::pair<int, int> > >q;

	std::queue<int>order_q;//用于获取编号的
	int ok = 0;//进程结束
	while (ok < N) {
		for (int i = 1; i <= N; i++) {
			if (!work[i].isvisited) {
				if (work[i].reach_time <= now_time) {//把小于当前时间已经到达的进程排序
					work[i].isvisited = 1;
					q.push({ work[i].pre,work[i].kth});
				}
				else {
					break;//说明后面的进程是,谁先来设服务
				}
			}
		}
		if (q.empty()) {//队列为空说明应该执行先来先服务,当前时刻最短
			for (int i = 1; i <= N; i++) {
				if (!work[i].isvisited) {
					work[i].isvisited = 1;
					new_job = work[i].kth;//获取进程编号
					break;
				}
			}
		}
		else {
			new_job = q.top().second;
			q.pop();
		}
		order_q.push(new_job);
		ok++;
		work[new_job].start_time = std::max(now_time,work[new_job].reach_time);
		now_time=work[new_job].finish_time = work[new_job].start_time + work[new_job].need_time;
		work[new_job].cir_time = work[new_job].finish_time - work[new_job].reach_time;
		sum_cir_time += work[new_job].cir_time;
		work[new_job].pre_cir_time = work[new_job].cir_time * 1.0 / work[new_job].need_time;
		sum_pre_cir_time += work[new_job].pre_cir_time;
	}

	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t优先权  \t结束时间\t周转时间\t带权周转时间\n";
	while (!order_q.empty()) {
		int i = order_q.front(); order_q.pop();
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t"<<work[i].pre<<"\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";

	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";
}


void QHPF(){//优先权抢占式
	std::cout << "\n\t\t\t\t\t优先权抢占算法\n\n";
	double sum_cir_time = 0;//总的周转时间
	
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	std::queue<int>order_q;
	int pre = 1e5;//记录实时的pre
	int ok = 0,now_time=0,now_id=0,lst_id=0;//当前时间,当前编号,上一次的编号
	while (ok < N) {
		pre = 1e5;
		for (int i = 1; i <= N; i++) {
			if (work[i].reach_time <= now_time) {//当前程序可以执行
				if (pre>work[i].pre&&!work[i].isvisited) {//更换优先级更高的
					pre = work[i].pre;
					now_id = work[i].kth;//当前要运行的程序
				}
			}
		}
		
		//std::cout << pre << " " << now_id << "\n";
		if (work[now_id].run_time == 0) {
				work[now_id].start_time = now_time;//该进程开始时在这时候介入
		}
		//std::cout << now_time << "\n";

		if (now_id != lst_id) {//还有进程可以执行
			int tmp_pre = pre;
			int tmp_id=now_id;
			for (int i = 1; i <= N; i++) {//从当前时刻到该作业结束,中间由优先级更高的插入
				if (now_time + work[now_id].need_time - work[now_id].run_time >= work[i].reach
					&& tmp_id != work[i].kth&&!work[i].isvisited&&tmp_pre>work[i].pre) {
					tmp_id = work[i].kth;
					tmp_pre = work[i].pre;
					break;
				}
			}
			

			if (tmp_pre != pre) {//优先级更高的插入
				
				work[now_id].run_time += work[tmp_id].reach_time-now_time;
				
				now_time = work[tmp_id].reach_time;//更新为新进程的到达时间
				lst_id = now_id;
				if (work[now_id].run_time == work[now_id].need_time) {
					work[now_id].finish_time = now_time;
					order_q.push(now_id);
					work[now_id].isvisited = 1;
					ok++;
					continue;
				}
				std::cout << "**执行" << now_id << "被" << tmp_id << "打断!  还剩" << work[now_id].need_time - work[now_id].run_time << "未执行\n";
				
			}
			else {
				lst_id = now_id;//没有优先级更高的插入
				order_q.push(now_id);
				now_time += work[now_id].need_time - work[now_id].run_time;
				work[now_id].finish_time = now_time;
				work[now_id].isvisited = 1;
				ok++;
			}
			//std::cout << now_id << "   " << tmp_id << "  " << pre<<"  "<<tmp_pre <<"  "<<now_time<<"\n";
			

		}
		else {
			now_time++;
		}
	}
	std::cout << "进程名\t 到达时间\t开始时间\t服务时间\t优先权  \t结束时间\t周转时间\t带权周转时间\n";
	while (!order_q.empty()) {
		int i = order_q.front(); order_q.pop();
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].pre << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";

	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";

}

void OLD_RR() {//时间片轮转老进程优先
	std::cout << "\n\t\t\t\t\t时间片轮转算法(老进程优先)\n\n";
	double sum_cir_time = 0;//总的周转时间
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	std::queue<node>q;//用于进程
	std::vector<node>v;//存放每一个进程的就绪
	for (int i = 1; i <= N; i++)
		v.push_back(work[i]);//放入队列中
	q.push(*v.begin());
	int now_time = (*v.begin()).reach_time;
	work[(*v.begin()).kth].start_time = now_time;
	v.erase(v.begin());
	int ok = 0;
	while (q.size() || v.size()) {
		while (v.size() && (*v.begin()).reach_time <= now_time) {
			q.push(*v.begin());
			v.erase(v.begin());
		}
		//std::cout << now_time << "\n";
		if (q.front().run_time < q.front().need_time) {//时间片还未用完加入队尾
			std::cout << q.front().id << " ";
			int t = q.front().kth;
			//std::cout << t << "\n";
			now_time++;
			if (work[t].run_time == 0)
				work[t].start_time = now_time;
			work[t].run_time++;
			//std::cout << work[t].run_time <<"  "<<now_time<< "\n";
			if (work[t].run_time == work[t].need_time) {
				work[t].finish_time = now_time;
			}
			
			q.front().run_time++;
			
			q.push(q.front());
			q.pop();
			while (v.size() && (*v.begin()).reach_time <= now_time) {//有新作业到达,加入队列
				q.push(*v.begin());
				v.erase(v.begin());
			}
		}
		else {
			q.pop();
		}
	}
	work[1].start_time = work[1].reach_time;
	std::cout << "\n进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	for (int i = 1; i <= N; i++) {
		//work[i].finish_time = work[i].start_time + work[i].need_time;
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";

}

void NEW_RR() {
	std::cout << "\n\t\t\t\t\t时间片轮转算法(新进程优先)\n\n";
	double sum_cir_time = 0;//总的周转时间
	double sum_pre_cir_time = 0;//总的带权周转时间
	std::sort(work + 1, work + 1 + N, cmp1);//来的时间排序
	std::queue<node>q;//用于进程
	std::vector<node>v;//存放每一个进程的就绪
	for (int i = 1; i <= N; i++)
		v.push_back(work[i]);//放入队列中
	q.push(*v.begin());
	int now_time = (*v.begin()).reach_time;
	work[(*v.begin()).kth].start_time = now_time;
	v.erase(v.begin());
	int ok = 0;
	while (q.size() || v.size()) {
		while (v.size() && (*v.begin()).reach_time <= now_time) {
			q.push(*v.begin());
			v.erase(v.begin());
		}
		//std::cout << now_time << "\n";
		if (q.front().run_time < q.front().need_time) {//时间片还未用完加入队尾
			std::cout << q.front().id << " ";
			int t = q.front().kth;
			//std::cout << t << "\n";
			now_time++;
			if (work[t].run_time == 0)
				work[t].start_time = now_time;
			work[t].run_time++;
			//std::cout << work[t].run_time << "  " << now_time << "\n";
			if (work[t].run_time == work[t].need_time) {
				work[t].finish_time = now_time;
			}

			q.front().run_time++;
			int x = now_time;
			for (;; x++) {
				int f = 0;
				while (v.size() && (*v.begin()).reach_time <= x) {//有新作业到达,加入队列
					q.push(*v.begin());
					v.erase(v.begin());
					f=1;
				}
				if (!f) {
					break;
				}
			}
		
			q.push(q.front());
			q.pop();
		}
		else {
			q.pop();
		}
	}
	work[1].start_time = work[1].reach_time;
	std::cout << "\n进程名\t 到达时间\t开始时间\t服务时间\t结束时间\t周转时间\t带权周转时间\n";
	for (int i = 1; i <= N; i++) {
		//work[i].finish_time = work[i].start_time + work[i].need_time;
		work[i].cir_time = work[i].finish_time - work[i].reach_time;
		sum_cir_time += work[i].cir_time;
		work[i].pre_cir_time = work[i].cir_time * 1.0 / work[i].need_time;
		sum_pre_cir_time += work[i].pre_cir_time;
		std::cout << work[i].id << "\t" << work[i].reach_time << "\t\t" << work[i].start_time << "\t\t" <<
			work[i].need_time << "\t\t" << work[i].finish_time << "\t\t" << work[i].cir_time <<
			"\t\t" << work[i].pre_cir_time << "\n";
	}
	std::cout << "平均" << "\t\t\t\t\t\t\t\t\t" << sum_cir_time * 1.0 / N << "\t\t" << sum_pre_cir_time * 1.0 / N << "\n";

}

/*
A 0 4 4
B 1 3 2
C 2 5 3
D 3 2 5
E 4 4 1
*/

int main() {
	input();
	ouputinit();
	std::cout << "请输入要选择的优先权算法:\n(1)先来先服务(FCFS)\n(2)短进程优先(SPJF)\n(3)优先权算法\n(4)时间片轮转\n";
	int chose;
	std::cin >> chose;
	if (chose == 1) {
		FCFS();
	}
	else if (chose == 2) {
		SPJF();
	}
	else if (chose == 3) {
		std::cout << "  优先权是否抢占(是(1)/否(0))";
		int q;
		std::cin >> q;
		if (q == 0) {
			HPF();
		}
		else {
			QHPF();
		}
	}
	else if (chose == 4) {
		std::cout << "  时间片进程优先选择(老进程(1)/新进程(0))";
		int q;
		std::cin >> q;
		if (q == 1) {
			OLD_RR();
		}
		else {
			NEW_RR();
		}
	}
	//QHPF();
	//NEW_RR();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1632091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速生成个人信息测试数据

特点&#xff1a; 业务测试的数据比较多&#xff0c;苦于测试数据生成麻烦&#xff0c;用javascripthtmlcss快速生成页面并支持导出&#xff1b; 用途&#xff1a; 1、可用于频繁的功能测试&#xff1b; 2、可用于性能测试参数化&#xff1b; 3、可用于自动化测试参数&…

Python | Leetcode Python题解之第58题最后一个单词的长度

题目&#xff1a; 题解&#xff1a; class Solution:def lengthOfLastWord(self, s: str) -> int:ls[]for i in s.split():ls.append(i)return len(ls[-1])

二叉树理论和题目

二叉树的种类 在我们解题过程中二叉树有两种主要的形&#xff1a;满二叉树和完全二叉树。 满二叉树 满二叉树&#xff1a;如果一棵二叉树只有度为0的结点和度为 2 的结点&#xff0c;并且度为 0 的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。 这棵二叉树为满二叉树…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.4

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

Python绘制3D曲面图

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 探索Python中绘制3D曲面图的艺术 在数据可视化的世界中&#xff0c;3D曲面图是一种强大的工…

OpenCV如何模板匹配

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV如何实现背投 下一篇 &#xff1a;OpenCV在图像中寻找轮廓 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 matchTemplate()搜索图像贴片和输入图像之间…

Python学习笔记------异常

当检测到错误时&#xff0c;Python解释器就无法继续执行了&#xff0c;反而出现一些错误提示&#xff0c;就是所谓异常&#xff08;bug&#xff09; 1、异常的捕获方法 任何程序运行过程中都可能出现异常&#xff0c;我们可以在力所能及的范围内&#xff0c;对可能出现的bug提…

家庭教育-家长指导手册

背景介绍 写这篇文章的动机&#xff1a;我在抖音上一个视频中看到孩子洗了碗&#xff0c;家长翻一本打印的册子&#xff0c;从里面找表扬的话。这个册子左侧写了孩子的行为&#xff0c;比如&#xff1a;洗碗&#xff0c;右边写了家长应该说的表扬的话。 所以&#xff0c;我寻思…

[论文笔记]SEARCHING FOR ACTIVATION FUNCTIONS

引言 今天带来另一篇激活函数论文SEARCHING FOR ACTIVATION FUNCTIONS的笔记。 作者利用自动搜索技术来发现新的激活函数。通过结合详尽的搜索和基于强化学习的搜索&#xff0c;通过实验发现最佳的激活函数 f ( x ) x ⋅ sigmoid ( β x ) f(x) x \cdot \text{sigmoid}(βx…

MOS(My Oracle Support)怎么用?Oracle DBA必备技能!

MOS简介 老Oracle DBAer都知道MOS的前身是Metalink&#xff0c;2012年MOS替换掉原有的Metalink平台&#xff1b;MOS是Oracle提供的新一代在线支持平台&#xff0c;MOS平台整合了以前的Metalink功能&#xff0c;并提供了更强大的功能和用户体验。它允许客户提交和跟踪技术支持…

ubuntu系统搭建pytorch环境详细步骤【笔记】

实践设备&#xff1a;华硕FX-PRO&#xff08;NVIDIA GeForce GTX 960M&#xff09; 搭建PyTorch环境的详细步骤如下&#xff1a; 1.安装Ubuntu系统&#xff1a; 下载Ubuntu的镜像文件并制作启动盘。将启动盘插入计算机&#xff0c;启动计算机并按照提示安装Ubuntu系统。 2.…

QT c++ 代码布局原则 简单例子

本文描述QT c widget代码布局遵循的原则&#xff1a;实中套虚&#xff0c;虚中套实。 本文最后列出了代码下载链接。 在QT6.2.4 msvc2019编译通过。 所谓实是实体组件&#xff1a;比如界面框、文本标签、组合框、文本框、按钮、表格、图片框等。 所谓虚是Layout组件&#x…

vue2编写主体页面

目录 一. 导入两张图片 二. 新建主体vue 三. 修改路由 1. 新增主体界面Main.vue的路由 2. 完整router/index.js代码如下&#xff1a; 在Vue 2中编写一个主体页面通常意味着创建一个包含导航栏、侧边栏、内容区域等的布局。以下是使用Vue 2和Element UI框架来构建一个简单的…

USB HID报告描述符学习

参考资料 HID 报告描述符 (qq.com)https://mp.weixin.qq.com/s?__bizMzU1ODI3MzQ1MA&mid2247485748&idx1&sn112bd8014eb96b03308b3b808549e8d4&chksmfc284ff1cb5fc6e770c2d2ece46c17bf2529901b45a357938978fa62163723556ad497b05c47&cur_album_id3340417…

react完整项目搭建的思路

react完整项目搭建的思路 react完整项目搭建的思路1.使用creacte-react-app初始化项目2.安装所需插件:路由、网络、样式、组件库3.reactjs目录结构组织4. 配置路径别名4.配置路由5.网络配置,对axios进行封装》获取当前环境变量 6.配置代理解决跨域7.配置使用iconfont8.状态管理…

产品推荐 | BittWare基于Altera Agilex“M FPGA的lA-860m加速卡

01 产品概述 BittWare的lA-860m是一款Altera Agilex“M系列FPGA卡&#xff0c;针对吞吐量和内存密集型应用进行了优化。M 系列 FPGA 具有广泛的内存层次结构&#xff0c;包括集成高带宽存储器 &#xff08;HBM2e&#xff09; 和硬内存片上网络 &#xff08;NoC&#xff09;&am…

GitHub Desktop进行汉化

第一步下载github桌面版 官网&#xff1a;安装 GitHub Desktop - GitHub 文档 历史版本&#xff1a;https://github.cn.uptodown.com/windows/versions 本期下载版本3.3.11进行汉化&#xff0c;最新版不一定稳定。 网站打不开的可自取&#xff1a; 3.3.11版本安装包链接&a…

电子阅览室技术特点与应用分析

电子阅览室是一个开放式的硬件和软件的集成平台&#xff0c;通过对技术和产品的集成&#xff0c;把当前大量的各种文献载体数字化&#xff0c;将它们组织起来在网上服务。从理论上讲&#xff0c;数字图书馆是一种引入管理和应用数字化技术的方法&#xff0c;它的主要特点有&…

原生IP和住宅IP有什么区别?

原生IP和住宅IP在多个方面存在显著的区别。 从定义和来源来看&#xff0c;原生IP是指未经NAT&#xff08;网络地址转换&#xff09;处理的真实、公网可路由的IP地址&#xff0c;它直接从互联网服务提供商&#xff08;ISP&#xff09;获得&#xff0c;而不是通过代理服务器或VP…

Java进阶-JavaStreamAPI的使用

本文全面介绍了 Java Stream API 的概念、功能以及如何在 Java 中有效地使用它进行集合和数据流的处理。通过详细解释和示例&#xff0c;文章展示了 Java Stream API 在简化代码、提高效率以及支持函数式编程方面的优势。文中还比较了 Java Stream API 与其他集合处理库的异同&…