1. 程式人生 > 其它 >C++ 搶佔時優先順序程序排程

C++ 搶佔時優先順序程序排程

  • 先來先服務
  • 短程序優先演算法
  • 優先順序排程(搶佔)
  • 優先順序排程
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

struct PCB
{
    int id;                          // 程序id
    double turnaround_time;          // 週轉時間
    double weighted_turnaround_time; // 帶權週轉時間
    double wait_time;                // 等待時間
    double start_time;               // 開始時間
    double coming_time;              // 到達時間
    double service_time;             // 執行時間
    double finish_time;              // 完成時間
    int youxianji;                   // 優先順序
    double run_time;                 // 已執行時間
};

int n;                    // 程序個數
vector<PCB> process_list; // 輸入的程序序列
vector<PCB> res;          // 待輸出的結果佇列

void input_process_count()
{
    printf("請輸入程序數量:");
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        PCB pcb; // pcb初始化
        pcb.id = i + 1;
        pcb.run_time = 0;            // 初始時已執行時間為零
        pcb.start_time = -1;         // 為判斷是否第一次到達
        process_list.push_back(pcb); // 加入已初始化好的pcb
    }
}

void input_youxianshu() // 輸入優先順序
{
    for (int i = 0; i < n; i++)
    {
        printf("請輸入程序%d的優先順序:", process_list[i].id);
        scanf("%d", &process_list[i].youxianji);
    }
}

void input_coming_time() // 輸入到達時間
{
    for (int i = 0; i < n; i++)
    {
        printf("請輸入程序%d的到達時間:", process_list[i].id);
        scanf("%lf", &process_list[i].coming_time);
    }
}

void input_serve_time() // 輸入需要服務時間
{
    for (int i = 0; i < n; i++)
    {
        printf("請輸入程序%d所需時間", process_list[i].id);
        scanf("%lf", &process_list[i].service_time);
    }
}

int choose_method() // 輸入選擇的演算法
{
    int select = 0;
    cout << "*****************************************\n";
    cout << "1 \t    先來先服務演算法            *******\n";
    cout << "2 \t    短程序優先演算法            *******\n";
    cout << "3 \t    優先順序排程(搶佔)          *******\n";
    cout << "4 \t    優先順序排程(非搶佔)        *******\n";

    cout << "請選擇: ";
    cin >> select;
    return select;
}

int cmpByComingTime(PCB a, PCB b) // 按照到達時間從小到大排序
{
    return a.coming_time < b.coming_time;
}

int cmpByServiceTime(PCB a, PCB b) // 按照需要服務時間從大到小排序
{
    return a.service_time > b.service_time;
}

void FCFS()
{
    sort(process_list.begin(), process_list.end(), cmpByComingTime); // 先按照到達時間排序
    double time = process_list[0].coming_time;                       // 初始化時間
    for (int i = 0; i < n; i++)
    {
        PCB pcb = process_list[i]; // 因為已經按照時間排序,所以當前為待執行的程序
        // 更新當前程序的資訊
        pcb.start_time = time;
        pcb.wait_time = time - pcb.coming_time;
        pcb.finish_time = time + pcb.service_time;
        pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
        pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
        time = pcb.finish_time; // 以當前程序的時間更新time
        process_list[i] = pcb;
        res.push_back(pcb); // 加入結果佇列
    }
}

void SJF()
{
    int top = 0;
    vector<PCB> short_jobs;                                          // 定義短程序佇列 其中資料由大到小
    sort(process_list.begin(), process_list.end(), cmpByComingTime); // 按照到達時間初始化
    double time = process_list[0].coming_time;                       // 初始化時間
    while (top < n || !short_jobs.empty())                           // 如果兩個對列裡仍然存在元素
    {
        if (short_jobs.empty()) // 如果佇列未空,則加入當前已經到達的程序
            short_jobs.push_back(process_list[top++]);

        PCB pcb = short_jobs[int(short_jobs.size() - 1)]; // 取出時間最短的
        if (pcb.start_time == -1)
            pcb.start_time = time;
        // 更新pcb的時間
        pcb.wait_time = time - pcb.coming_time;
        pcb.finish_time = time + pcb.service_time;
        pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
        pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
        time = pcb.finish_time;

        // 加入到執行結束佇列
        res.push_back(pcb);
        short_jobs.pop_back();
        // 如果在上個程序執行期間有程序到達則加入short_jobs佇列
        for (; top < n && process_list[top].coming_time < time; top++)
        {
            short_jobs.push_back(process_list[top]);
        }
        // 因為有新的程序加入,所以對short_jobs進行排序
        sort(short_jobs.begin(), short_jobs.end(), cmpByComingTime);
    }
}

bool cmpByPriority(PCB a, PCB b) // 按照優先順序排序
{
    if (a.youxianji == b.youxianji)
        return a.coming_time > b.coming_time;
    return a.youxianji < b.youxianji;
}

void PriorityNo() // 非搶佔優先順序排程
{
    int top = 0; // 定義頭指標
    vector<PCB> priority_higher;
    sort(process_list.begin(), process_list.end(), cmpByComingTime);
    double time = process_list[0].coming_time;
    while (top < n || !priority_higher.empty()) // 如果仍有程序未執行結束
    {
        if (priority_higher.empty()) // 為空則加入新的程序
            priority_higher.push_back(process_list[top++]);

        PCB pcb = priority_higher[int(priority_higher.size() - 1)]; // 取出要執行的程序
        if (pcb.start_time == -1)                                   //如果是第一次抵達則更新時間
            pcb.start_time = time;

        // 更新pcb
        pcb.wait_time = time - pcb.coming_time;
        pcb.finish_time = time + pcb.service_time;
        pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
        pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
        time = pcb.finish_time;

        res.push_back(pcb);         // 執行結束則加入res
        priority_higher.pop_back(); // 並刪除已執行結束的程序

        for (; top < n && process_list[top].coming_time < time; top++)
        { // 加入在此期間到達的程序
            priority_higher.push_back(process_list[top]);
        }
        // 因為有新程序加入,進行排序
        sort(priority_higher.begin(), priority_higher.end(), cmpByPriority);
    }
}

void PriorityYes()
{
    int top = 0;
    vector<PCB> priority_higher;
    sort(process_list.begin(), process_list.end(), cmpByComingTime);
    double time = process_list[0].coming_time;  // 初始化時間
    while (top < n || !priority_higher.empty()) // 如果仍有程序未結束
    {
        if (priority_higher.empty()) // 如果為空,則加入新的程序
            priority_higher.push_back(process_list[top++]);

        PCB pcb = priority_higher[int(priority_higher.size() - 1)]; // 取出優先順序最高的程序執行
        if (pcb.start_time == -1)                                   // 如果是第一次到達,則記錄開始時間
        {
            pcb.start_time = time;
            pcb.wait_time = pcb.start_time - pcb.coming_time;
        }
        if (top < n && process_list[top].coming_time <= time + pcb.service_time - pcb.run_time) // 如果仍有未加入的程序, 並且在執行期間有新的程序到達
        {
            pcb.run_time += process_list[top].coming_time - time;                // 則先執行距離下個程序到達的時間
            time += process_list[top].coming_time - time;                        // 並更新時間
            priority_higher[priority_higher.size() - 1] = pcb;                   // 更新佇列
            priority_higher.push_back(process_list[top++]);                      // 把下一個程序加入
            sort(priority_higher.begin(), priority_higher.end(), cmpByPriority); // 並進行排序
            if (pcb.run_time == pcb.service_time)                                // 如果當前程序的執行時間已經夠了,則更新pcb資訊,並刪除程序
            {
                pcb.finish_time = time;
                pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
                pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
                res.push_back(pcb);
                priority_higher.pop_back();
            }
        }
        else // 如果沒有新的程序到達, 則將當前程序執行完畢
        {
            pcb.finish_time = time + pcb.service_time - pcb.run_time;
            pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
            pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
            time = time + pcb.service_time - pcb.run_time;
            res.push_back(pcb); // 執行完畢則加入res
            priority_higher.pop_back();
        }
    }
}

bool cmpById(PCB a, PCB b)
{
    return a.id < b.id;
}

void print_schedulInfo()
{
    printf("程序編號\t提交時間\t執行時間\t開始時間\t等待時間\t完成時間\t週轉時間\t帶權週轉時間\n");
    // cout << res.size() << endl;
    sort(res.begin(), res.end(), cmpById); // 按照ID排序
    double start = 0x3f3f3f3f3f, end = 0;
    double allTT = 0, allWTT = 0, runTime = 0;
    for (int i = 0; i < n; i++)
    {
        PCB pcb = res[i];
        start = min(start, pcb.start_time);     // 得到開始時間
        end = max(end, pcb.finish_time);        // 所有程序結束時間
        allTT += pcb.turnaround_time;           // 總的週轉時間
        allWTT += pcb.weighted_turnaround_time; // 總的帶權週轉時間
        runTime += pcb.service_time;            // 總的服務時間
        printf("%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n", pcb.id, pcb.coming_time, pcb.service_time, pcb.start_time, pcb.wait_time, pcb.finish_time, pcb.turnaround_time, pcb.weighted_turnaround_time);
    }

    printf("平均週轉時間%.2f\t平均帶權週轉時間%.2f\tCPU利用率%.2f\t系統吞吐量%.2f\n", allTT / n, allWTT / n, (runTime) / (end - start), (n) / (end - start));
}

int main()
{
    // 4 1 1 1 1 9 8 8.4 8.8 0.2 2 1 0.5
    // 4 2 4 3 1 10 20 30 50 20 30 25 20
    // 4 1 2 3 2 0 2 4 5 7 4 1 4
    input_process_count();        // 輸出程序數量
    input_youxianshu();           // 輸入優先順序數
    input_coming_time();          // 輸入到達時間
    input_serve_time();           // 輸入需要服務時間
    int choose = choose_method(); // 得到使用者選擇的數
    // printf("%d\n", choose);
    switch (choose)
    {
    case 1:
        FCFS(); // 先來先服務
        break;
    case 2:
        SJF(); // 短作業優先
        break;
    case 3:
        PriorityYes(); // 優先順序搶佔式
        break;
    default:
        PriorityNo(); // 優先順序非搶佔式
        break;
    }
    print_schedulInfo(); // 列印結果
    return 0;
}