操作系统调度算法-HRRN高优先级调度算法

高优先级调度算法:

算法思想

按照优先级(等待时间 + 要求服务时间) / 要求服务时间进行排序,总是运行优先级最高的进程不可抢占,只有当前进程运行完了才考虑其他进程的运行。

优缺点

综合考虑了等待时间换运行时间(要求时间),等待时间相同时,要求服务时间短的优先(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;
}

posted @ 2021-12-15 16:57  梨花满地  阅读(826)  评论(5编辑  收藏  举报