高优先级调度算法:
算法思想
按照优先级(等待时间 + 要求服务时间) / 要求服务时间进行排序,总是运行优先级最高的进程不可抢占,只有当前进程运行完了才考虑其他进程的运行。
优缺点
综合考虑了等待时间换运行时间(要求时间),等待时间相同时,要求服务时间短的优先(SJF的优点);要求服务时间相同时,等待时间长的优先(FCFS的优点),随着等待时间越来越长,响应比也会越来越大,避免了长作业饥饿的问题。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <vector>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable : 4996)
using namespace std;
const int N = 1e5 + 10;
enum Status{running, ready, blocked, finished};
string status[] = { "running", "ready", "blocked", "finished"};
int n;
struct PCB//程序控制块
{
string id;
int startblock;//到达时间
int alltime;//总时间
int blocktime;//阻塞时间
int cputime;//运行时间
int starttime;
int end_time;//结束时间
int turnover_time;//周转时间
double response_ratio;//优先级
Status state;//进程状态
struct PCB* next;
} P[N];
bool operator < (PCB a, PCB b) {//重载小于号 按照进程剩余时间进行排序
if (a.state == finished)return 1;
else if (b.state == finished)return 1;
return a.alltime - a.cputime > b.alltime - b.cputime;
}
bool cmp1( PCB& p1, PCB& p2)//按照到达时间从小到大排序,到达时间一样按照总时间从小到大排序
{
if (p1.startblock == p2.startblock)
return p1.alltime < p2.alltime;
return p1.startblock < p2.startblock;
}
void setstarttime(string id, int starttime, PCB* l);
bool cmp2(PCB& p1, PCB& p2)//按照优先级从大到小排序 优先级一样按照开始时间从大到小排序
{
return (p1.response_ratio > p2.response_ratio) || (p1.response_ratio == p2.response_ratio && p1.startblock < p2.startblock);
}
void display(PCB* p);
void HRRN(PCB* p)//HRRN高优先级调度算法
{
string sequence = "";//程序运行序列
int i, j, now;
now = 0, j = 0;
sort(p, p + n, cmp1);
for (i = 0; i <= n; i++)
{
while (j < n && p[j].startblock <= now) {//找当前已经到达的所有进程
p[j++].state = ready;
}
for (int k = j + 1; k < n; k++)p[k].state = blocked;
for (int k = i; k < j; k++)
p[k].response_ratio = (now - p[k].startblock + p[k].alltime) / p[k].alltime; //重新计算优先级 i~j
sort(p + i, p + j, cmp2);//按优先级排序
//优先级最高的程序已经到达队首,运行队首程序,更改队首程序参数
if (p[i].startblock > now)//当前时间还没有到该进程的到达时间
p[i].end_time = p[i].startblock + p[i].alltime;
else //到该进程已经到达
p[i].end_time = now + p[i].alltime;
p[i].state = running;//设置状态
sequence += p[i].id;
setstarttime(p[i].id, now, p);
p[i].turnover_time = p[i].end_time - p[i].startblock;
now = p[i].end_time;
if (i)p[i - 1].state = finished, p[i - 1].cputime = p[i - 1].alltime;
else if (i == n - 1)p[i].state = finished, p[i].cputime = p[i].alltime;
display(p);
}
cout << "程序的运行序列(HRRN算法):";
for (int i = 0; i < (int)sequence.size(); i++) {
if (i != (int)sequence.size() - 1) cout << sequence[i] << "->";
else cout << sequence[i];
}
cout << endl;
}
void setPCB(PCB p, PCB *l) {//设置PCB运行时间,结束时间,状态
for (int i = 0; i < n; i++) {
if (l[i].id == p.id) {
l[i].cputime = p.cputime;
l[i].end_time = p.end_time;
l[i].state = p.state;
return;
}
}
}
void setState(string id, Status st, PCB* l) {//设置PCB控制块的状态
for (int i = 0; i < n; i++) {
if (l[i].id == id) {
l[i].state = st;
return ;
}
}
}
void setstarttime(string id, int starttime, PCB* l) {//设置进程开始时间
for (int i = 0; i < n; i++) {
if (l[i].id == id) {
l[i].starttime = starttime;
return;
}
}
}
void SRTF(PCB *p) {//最短剩余时间优先算法
string sequence = "";//程序运行序列
int j = 0;// 当前时间
priority_queue<PCB>arr;//已经就绪的进程队列
queue<PCB> q;//进程总队列
sort(p, p + n, cmp1);//按照到达时间排序
for (int i = 0; i < n; i++)q.push(p[i]);
int now = -1;
int solve = 0;
while (1) {
++now;
cout << "当前时间:" << now << endl;
bool flag = 0;
//每当当前有任务到达时,重新排序未执行完的进程的剩余时间
while (q.size() && q.front().startblock <= now) {//找到当前已经到达的任务
PCB a = q.front();
setState(a.id, ready, p);
arr.push(a);
q.pop();
flag = 1;
}
PCB a = arr.top();
arr.pop();
//运行当前程序,更改当前程序参数
if(a.cputime == 0)setstarttime(a.id, now, p);
a.end_time = now;
a.cputime = min(a.cputime + 1, a.alltime);//运行时间 + 1
a.state = running;
sequence += a.id;
setPCB(a, p);
if(a.cputime >= a.alltime){//当前任务已经运行完成 设置对应参数
setState(a.id, finished, p);
solve++;
}
display(p);
if (a.cputime < a.alltime) {//还没有运行完
setState(a.id, ready, p);
arr.push(a);
}
if (solve >= n)break;
}
char temp = sequence[0];
cout << "程序的运行序列(SRTF算法):";
cout << temp << ' ';
for (int i = 1; i < (int)sequence.size(); i++) {
if (temp != sequence[i]) {
cout << sequence[i] << ' ';
}
temp = sequence[i];
}
cout << endl;
}
void display(PCB *p) {//输出进程调度情况
double sum = 0;
cout << "进程名称\t" << "到达系统时间\t" << "所需服务时间\t" << "开始时间\t" << "结束时间\t" << "已经服务时间\t" << "状态" << endl;
for (int i = 0; i < n; i++)
{
cout << p[i].id << "\t\t" << p[i].startblock << "\t\t" << p[i].alltime << "\t\t" << p[i].starttime << "\t\t" << p[i].end_time << "\t\t" << p[i].cputime << "\t\t" << status[p[i].state] << endl;
sum += p[i].turnover_time;
}
//cout << "平均周转时间: " << sum / n << endl;
}
int main()
{
n = 5;
ios::sync_with_stdio(0);
freopen("a.txt", "r", stdin);
cout << "请输入五个进程的名称, 开始时间,要求服务时间:\n";
for (int i = 0; i < n; i++) {
cin >> P[i].id >> P[i].startblock >> P[i].alltime;
P[i].state = blocked;
}
HRRN(P);
return 0;
}