給出進程啓動區間計算任意時間點並行進程數量

題目:原題不公開,需求是給出大量進程的啓動和結束時間,計算任意時間點進程併發數。進程數有限,查詢次數很大。關閉開區間: [啓動,關閉)

思路:先將時間區間點排序,然後遍歷計數,遇到啓動+1,遇到關閉-1,時間點切換時,就得出上個值到當前值區間的進程數

接口定義如下:

void number_of_tasks_running(
        OUT int result[],  //輸出結果
        IN int start[],    //啓動時間點
        IN int end[],      //結束時間點
        IN int n,          //進程數
        IN int query[],    //查詢種子
        IN int m)          //查詢數量
原版本代碼所有算法都是自行實現的,效率要好一些但是篇幅偏長,下文的代碼用stl簡化了一下


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

#define IN
#define OUT
#define INT_MIN  0
#define INT_MAX  0x7fffffff

typedef enum
{
        S_START,
        S_END,
} status_t;

class Node
{
public:
        status_t m_type;
        int m_value;
        Node(){}
        Node(int value, status_t type):m_type(type), m_value(value){}
        bool operator<(const Node& n2) const
        {
                return m_value < n2.m_value || (m_value == n2.m_value && m_type == S_START);    //升序排列,開始在前
        }
};

class Range
{
public:
        uint32_t m_beg;
        uint32_t m_end;
        Range(uint32_t beg, uint32_t end) : m_beg(beg), m_end(end) {}
        bool operator<(const Range& n2) const
        {
                if(n2.m_beg >= m_beg && n2.m_end < m_end)
                        return false;
                return m_beg < n2.m_beg;
        }
};

/*
 * 功能:合併區間,計數
 */
void CountRange(vector<Node>& points, map<Range, int>& rst)
{
        if(points.size() < 2)
                return;
        //計算合併區間數
        int cnt = 0;
        int last = INT_MIN;
        int beg = last;
        for(vector<Node>::iterator itr = points.begin(); itr != points.end(); itr++)
        {
                if(itr->m_value != last)
                {
                        rst[Range(beg, itr->m_value)] = cnt;
                        last = itr->m_value;
                        beg = last;
                }
                if(itr->m_type == S_START)
                        cnt++;
                else
                        cnt--;
        }
        rst[Range(beg, INT_MAX)] = 0;   //後開區間
}

/*
 * 功能:計算並行任務數量
 */
void number_of_tasks_running(
        OUT int result[],
        IN int start[],
        IN int end[],
        IN int n,
        IN int query[],
        IN int m)
{
        //點序列
        vector<Node> points;
        points.resize(2*n);
        for(int i = 0; i < n; i++)
        {
                points[i] = Node(start[i], S_START);
                points[i+n] = Node(end[i], S_END);
        }
        //排序,計算最小一致區間
        sort(points.begin(), points.end());
        map<Range, int> rst;
        CountRange(points, rst);
        //
        for(map<Range, int>::iterator itr = rst.begin(); itr != rst.end(); itr++)
                printf("%d - %d %d\n", itr->first.m_beg, itr->first.m_end, itr->second);

        //
        for(int i = 0; i < m; i++)
        {
                map<Range, int>::iterator itr = rst.find(Range(query[i], query[i]+1));
                result[i] = itr->second;
        }
}

//以下是測試代碼
/*
 * 功能:打印數組
 */
void dump_array(int arr[], int size, const char* info)
{
        int i;
        printf("%s\t:[", info);
        for(i = 0; i < size; i++)
                printf("%2d, ", arr[i]);
        printf("]\n");
}

int main(int agc, char* argv[])
{
        int start[] = {0, 2, 5};
        int end[] = {4, 7, 8};
        int n = sizeof(start)/sizeof(int);
        int query[] = {1, 9, 4, 3, -1, 0, 2, 4, 5, 7, 8};
        int m = sizeof(query)/sizeof(int);
        int* rst = new int[m];
        number_of_tasks_running(rst, start, end , n, query, m);
        dump_array(start, n, "start");
        dump_array(end, n, "end");
        dump_array(query, m, "query");
        dump_array(rst, m, "out");
        delete rst;
        return 0;
}

發佈了87 篇原創文章 · 獲贊 13 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章