每日一练——轮询调度算法和短作业优先调度算法的平均等待时间

今天做 亚信的笔试题遇到的轮询调度算法,和春招做的百度笔试题短作业优先调度算法很相似,但是难度要UPUP。做题的过程中,因为没有正确地处理迭代器失效的问题浪费了好多时间(>﹏<。)~,看来有必要把STL再看一遍了!不废话了,直接上题目。
轮询调度算法
如果一个系统可以在单个CPU上运行多个并发作业,那么就该系统而言,“调度”是指:系统选择运行哪些任务,何时运行,何时中断以及以何种方式运行或中断。轮询调度规则是指:每个作业运行时间固定,该作业结束后,切换到下一个作业。一个作业的等待时间是指运行前需要等待的总时间。每个作业会在特定时间到达,等待调度,并占用一段固定时间运行。新作业到达后系统会把该作业正在等待CPU的现有作业之后。
题目描述:
给定提交列表,使用轮询策略计算所有作业的平均等待时间。函数wait_time_robin包含两个含有作业到达时间arrival和作业运行时间run的整数数组,还有一个表示作业数的整数n,和一个表示轮询策略使用的固定时长得整数q。作业到达时间和作业运行时间根据作业到达时间升序排列。对于同时到达的作业,按照其在到达时间数组中的顺序处理,可以假设,作业到达时,CPU一直未空闲。返回值为使用轮询策略算出的作业平均等待时间(浮点数)。

假设 0 <= 作业到达时间 < 100 且 0  < 作业运行时间 < 100。

#include <iostream>
#include <vector>
using namespace std;

float wait_time_robin(int *arrival, int *run, int n, int q)
{
    vector<int> wait_queue;//等待队列 存放还没运行的任务
    vector<int> task_queue;//任务队列 存放正在运行的任务

    int cur_time = 0;
    int *predict_end_time = new int[n];//预计结束的时间
    int *actual_end_time = new int[n];//实际结束的时间
    int *run_time = new int[n];

    for (int i = 0; i < n; i++)
    {
        predict_end_time[i] = arrival[i] + run[i];
        wait_queue.push_back(i);
        run_time[i] = run[i];
    }

    while (wait_queue.size() != 0 || task_queue.size() != 0)
    {
        for (vector<int>::iterator iter1 = wait_queue.begin(); iter1 != wait_queue.end();)
        {
            if (arrival[*iter1] <= cur_time)
            {
                task_queue.push_back(*iter1);//如果有任务到来,则把该任务从等待队列转到任务队列
                iter1 = wait_queue.erase(iter1);
            }
            else
            {
                iter1++;
            }
        }

        if (wait_queue.size() > 0 && task_queue.size() == 0)//正在运行的任务队列里没有任务,等待队列里还有任务,但是任务还没来
        {
            cur_time++;
        }

        for (vector<int>::iterator iter2 = task_queue.begin(); iter2 != task_queue.end();)//依次处理任务队列的任务
        {
            if (run_time[*iter2] > q)//该任务剩余运行时间大于调度时间
            {
                cur_time += q;
                run_time[*iter2] -= q;
            }
            else//该任务剩余运行时间小于于调度时间
            {
                cur_time += run_time[*iter2];
                run_time[*iter2] = 0;
                actual_end_time[*iter2] = cur_time;//记录下该任务实际完成时间
            }
            int index  = *iter2;//在下面可能有push_back操作会导致iter2失效,故先保存下来
            task_queue.erase(iter2);//当前任务已经运行过,从队头移除

            for (vector<int>::iterator iter1 = wait_queue.begin(); iter1 != wait_queue.end();)
            {
                if (arrival[*iter1] <= cur_time)
                {
                    task_queue.push_back(*iter1);//这里会导致iter2迭代器失效
                    iter1 = wait_queue.erase(iter1);
                }
                else
                {
                    iter1++;
                }
            }

            if (run_time[index] > 0)//当前任务还没运行完
            {
                task_queue.push_back(index);//添加到任务队列后面
            }

            iter2 = task_queue.begin();//iter2重新指向队头
        }

    }

    float sum_time = 0;

    for ( i = 0; i < n; i++)
    {
        sum_time = sum_time + actual_end_time[i] - predict_end_time[i];//等待时间 = 实际结束时间- 预计结束时间
    }

    delete []predict_end_time;
    delete []actual_end_time;
    delete []run_time;

    return sum_time / n;
}

int main(int argc, char* argv[])
{
    int arrival[]= {10, 11, 14};
    int run[] = {5, 2, 3};
    cout << wait_time_robin(arrival, run, 3, 3) << endl;
    return 0;
}
短作业优先调度算法(SJF)
短作业优先调度算法(Short Job First)用于进程调度时又被称为短进程优先调度算法(Short Process First),该算法既可以用于作业调度,又可以用于进程调度。 
在作业调度中,该算法每次从后备作业队列中挑选估计服务时间最短的一个或几个作业,将他们调入内存,分配必要的资源,创建进程并放入就绪队列。在进程调度中的原理类似。
问题描述:
假设有n项作业位于就绪队列中,这些作业的提交时间用数组arrival按照提交时间的先后顺序存储,对应的作业服务时间(持续时间)用数组run存储。采用SJF算法,计算n项作业的平均等待时间。当存在多个相同长度的短作业时,按照提交时间的先后顺序进行调度。假设0<= n <= 100。

#include <iostream>  
#include <vector>  
using namespace std;  

float min_wait_time(int *arrival, int *run, int n)
{
    vector<int> wait_queue;//等待队列
    vector<int> task_queue;//任务队列
    int *predict_end_time = new int[n];//预计结束的时间  
    int *actual_end_time = new int[n];//实际结束的时间  

    int cur_time = 0;
    for (int i = 0; i < n; i++)  
    {   
        predict_end_time[i] = arrival[i] + run[i];  
        wait_queue.push_back(i); 
    }

    while (wait_queue.size() != 0 || task_queue.size() != 0)
    {
        if (wait_queue.size() > 0 && arrival[(*wait_queue.begin())] <= cur_time)//有新任务到来,加到任务队列中
        {
            for (vector<int>::iterator iter = wait_queue.begin(); iter != wait_queue.end();)
            {
                if (arrival[*iter] <= cur_time)
                {
                    task_queue.push_back(*iter);
                    iter = wait_queue.erase(iter);
                }
                else
                {
                    break;
                }
            }

        }
        else if (task_queue.size() > 0)//任务队列有任务,执行任务
        {
            vector<int>::iterator min_iter = task_queue.begin();
            for (vector<int>::iterator iter = task_queue.begin(); iter != task_queue.end(); iter++)
            {
                if (run[*iter] < run[*min_iter])//记录下用时最少的
                {
                    min_iter = iter;
                }
            }
            cur_time += run[*min_iter];//执行任务
            actual_end_time[*min_iter] = cur_time;//记录下实际完成时间
            task_queue.erase(min_iter);
        }
        else//如果任务队列里没任务,等待队列里有任务但未到来
        {
            cur_time++;
        }
    }
    float sum_time = 0;  

    for ( i = 0; i < n; i++)  
    {  
        sum_time = sum_time + actual_end_time[i] - predict_end_time[i];//等待时间 = 实际结束时间- 预计结束时间  
    }  

    delete []predict_end_time;  
    delete []actual_end_time;  

    return sum_time / n;  
}

int main(int argc, char* argv[])  
{  

    int arrival[]= {0, 2, 4, 25};  
    int run[] = {7, 4, 1, 4};

    cout << min_wait_time(arrival, run, 4) << endl;

    return 0;  
} 




你可能感兴趣的:(每日一练——轮询调度算法和短作业优先调度算法的平均等待时间)