1. 程式人生 > >每日一練——輪詢排程演算法和短作業優先排程演算法的平均等待時間

每日一練——輪詢排程演算法和短作業優先排程演算法的平均等待時間

今天做亞信的筆試題遇到的輪詢排程演算法,和春招做的百度筆試題短作業優先排程演算法很相似,但是難度要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;  
}