基于优先队列的作业调度算法实现

实训作业

#include <bits/stdc++.h>
#include <windows.h>

using namespace std;

typedef long long LL;
mt19937_64 gen(time(0));

struct node {      //定义作业的属性,放在结构体里
    int start;     //开始时间
    int end;       //结束时间
    int num;       //作业编号
    int w;         //优先数
    int wait = 0;  //等待时间
} e[50], h[1000010];

bool cmp(node a, node b) { return a.start < b.start; }

int randInt(int l, int r) {
    return gen() % (r - l + 1) + l;
}  //生成[l,R]的int型数字
LL randLL(LL l, LL r) {
    return gen() % (r - l + 1) + l;
}  //生成[l,R]的 long long int型数字

void loading() {  //打印数据处理进度条
    printf("\n数据处理中,请稍后……\n");
    for (int i = 1; i <= 5; i++) {
        printf("[");
        for (int j = 1; j <= i; j++) printf("■■");
        for (int j = 0; j < 5 - i; j++) printf("□□");
        printf("]\t%d%%", i * 20);
        Sleep(1000);
        printf("\r");
    }
    printf("\n\n");
    return;
}

void loading2() {  //打印数据处理进度条
    printf("\n数据生成中,请稍后……\n");
    for (int i = 1; i <= 2; i++) {
        printf("[");
        for (int j = 1; j <= i; j++) printf("■■■■■");
        for (int j = 0; j < 2 - i; j++) printf("□□□□□");
        printf("]\t%d%%", i * 50);
        Sleep(1000);
        printf("\r");
    }
    printf("\n\n");
    return;
}

int cnt = 0;  //小顶堆中作业个数

void create(int x, int k) {  //建立小顶堆
    h[++cnt].w = x;
    h[cnt].num = k;
    int t = cnt;
    while (t > 1 && h[t / 2].w > h[t].w) {
        swap(h[t], h[t / 2]);
        t /= 2;
    }
    h[t].w = x;
    return;
}

// void update() {  //更新小顶堆(劣质版)
//     for (int i = cnt; i >= 2; i--)
//         if (h[i / 2].w > h[i].w) swap(h[i / 2], h[i]);
//     return;
// }

void down(int u) {  //更新小顶堆(新版)
    int t = u;
    if (2 * u <= cnt && h[2 * u].w < h[t].w) t = 2 * u;
    if (2 * u + 1 <= cnt && h[2 * u + 1].w < h[t].w) t = 2 * u + 1;
    if (t != u) {
        swap(h[t], h[u]);
        down(t);
    }
    return;
}

bool judge(string s) {  //判断字符串是否完全由数字构成,即字符串是否合法
    for (int i = 0; i < s.size(); i++)
        if (s[i] >= '0' && s[i] <= '9')
            continue;
        else
            return false;
    return true;
}

void check(int k)  //调度核心函数
{
    int ans = 1;
    sort(e, e + k, cmp);
    int flag = 0;
    int time;
    for (int i = 1; i <= 2000; i++) {
        if (i == time) flag = 0;
        for (int j = 0; j < k; j++)
            if (e[j].start == i) create(e[j].end, j);
        if (cnt > 0) {
            if (flag == 0) {
                int tot = h[1].num;
                int weight = h[1].w;
                swap(h[1], h[cnt]);
                cnt--;
                down(1);
                printf(
                    "%d-编号为%d的作业于%d时进入队列\t于%d时开始调度\t于%d"
                    "时离开\t调度时长为%d\t该作业等待时间为"
                    "%d\t执行该作业时该作业的优先数为"
                    "%d    优先数动态变化情况%d -> %d\n",
                    ans++, e[tot].num, e[tot].start, i,
                    i + e[tot].end - e[tot].start, e[tot].end - e[tot].start,
                    e[tot].wait, weight, e[tot].end, weight);
                flag = 1;
                time = i + e[tot].end - e[tot].start;
            }
            for (int i = 1; i <= cnt; i++) {
                e[h[i].num].wait++;
                h[i].w -= e[h[i].num].wait;
            }
        }
    }
    return;
}

void color(int x) {
    if (x == 0)  //白色
        return;
    else if (x == 1)  //红色
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
                                FOREGROUND_INTENSITY | FOREGROUND_RED);
    else if (x == 2)  //绿色
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
                                FOREGROUND_INTENSITY | FOREGROUND_GREEN);
    else if (x == 3)  //蓝色
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
                                FOREGROUND_INTENSITY | FOREGROUND_BLUE);
    else if (x == 4)  //粉色
        SetConsoleTextAttribute(
            GetStdHandle(STD_OUTPUT_HANDLE),
            FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
    else if (x == 5)  //青色
        SetConsoleTextAttribute(
            GetStdHandle(STD_OUTPUT_HANDLE),
            FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
    else if (x == 6)  //黄色
        SetConsoleTextAttribute(
            GetStdHandle(STD_OUTPUT_HANDLE),
            FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
    else if (x == 7)  //随机生成
        color(randInt(0, 6));
    return;
}

int main() {
    printf(
        "\n***************************************************\n");  //输出文字信息
    printf("*         -基于优先队列的作业调度算法实现-        *\n");
    printf("*                   作者:孙黎明                  *\n");
    printf("***************************************************\n\n");

    printf("\n----------字体颜色----------\n");
    printf("0.白色\n");
    printf("1.红色\n");
    printf("2.绿色\n");
    printf("3.蓝色\n");
    printf("4.粉色\n");
    printf("5.青色\n");
    printf("6.黄色\n");
    printf("7.随机生成\n");
    printf("-----------------------------\n");
    printf("\n请输入您想用字体颜色的编号:");
    string tmp;
    while (getline(cin, tmp)) {
        if (tmp == "0" || tmp == "1" || tmp == "2" || tmp == "3" ||
            tmp == "4" || tmp == "5" || tmp == "6" || tmp == "7") {
            color(stoi(tmp));
            break;
        } else
            printf("非法输入,请重新输入:");
    }

    printf("\n   ----------菜单----------\n");
    printf("   1.手动输入作业信息\n");
    printf("   2.电脑自动生成作业信息\n");
    printf("   3.退出\n");
    printf("   ------------------------\n");
    printf("\n请输入您所选的操作编号:");
    string s, str;
    while (getline(cin, s)) {
        if (s == "1" || s == "2" || s == "3")
            break;
        else
            printf("非法输入,请重新输入:");
    }
    if (s == "1") {
        printf("请输入作业个数(0-15的数字):");
        while (getline(cin, str)) {
            if (judge(str) && stoi(str) >= 0 &&
                stoi(str) <= 15) {  //判断输入是否合法
                int num = stoi(str);
                if (num == 0) {
                    printf("当前没有作业需要被调度\n");
                    break;
                }
                printf("请按顺序给出%d个作业的开始时间和结束时间\n", num);
                for (int i = 0; i < num; i++) {
                    printf(
                        "请输入第%d个作业的开始时间和结束时间,中间用空格间隔("
                        "1<=时间<=100):",
                        i + 1);
                    string str1, str2;
                    while (cin >> str1) {
                        cin >> str2;
                        if (judge(str1) && judge(str2) && stoi(str1) >= 1 &&
                            stoi(str1) <= 100 && stoi(str2) >= 1 &&
                            stoi(str2) <= 100 && stoi(str2) > stoi(str1)) {
                            e[i].start = stoi(str1);
                            e[i].end = stoi(str2);
                            e[i].num = i + 1;
                            break;
                        } else
                            printf("非法输入,请重新输入:");
                    }
                }
                loading();
                check(num);
                break;
            }
            printf("非法输入,请重新输入:");
        }
    } else if (s == "2") {
        printf("请输入自动生成作业个数(0-15的数字):");
        while (getline(cin, str)) {
            if (judge(str) && stoi(str) >= 0 && stoi(str) <= 15) {
                loading2();
                int num = stoi(str);
                int k = 0;
                while (k != num) {
                    int a = randInt(1, 100);  //生成随机数
                    int b = randInt(1, 100);
                    if (a < b) {  //去掉生成的非法随机数
                        e[k].start = a;
                        e[k].end = b;
                        e[k].num = k + 1;
                        k++;
                    }
                }
                if (k == 0) {
                    printf("当前没有作业需要被调度\n");
                    break;
                }
                printf("\n自动生成的数据如下:\n");
                for (int i = 0; i < k; i++)
                    printf("第%d个作业的开始时间是:%d,结束时间是:%d\n", i + 1,
                           e[i].start, e[i].end);
                loading();
                check(k);
                break;
            } else
                printf("非法输入,请重新输入:");
        }
    }
    printf("\n谢谢使用!( ̄︶ ̄)↗\n");  //程序结束
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
                            FOREGROUND_INTENSITY | FOREGROUND_RED |
                                FOREGROUND_GREEN |
                                FOREGROUND_BLUE);  //将字体重新设置为白色
    return 0;
}

版权声明:本文为qq_34035720原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。