机器调度问题

来源:互联网 发布:druid slf4j打印sql 编辑:程序博客网 时间:2024/05/16 01:41

1)问题描述

机器调度是指m台机器需要处理n个作业,设作业i的处理时间为ti,则对n个作业进行机器分配,使得:

(1) 一台机器在同一时间内只能处理一个作业;

(2) 一个作业不能同时在两台机器上处理;

(3) 作业i一旦运行,则需要ti个连续时间单位。

设计算法进行合理调度,使得在m台机器上处理n个作业所需要的处理时间最短。

2) 基本要求

(1) 建立问题模型,设计数据结构;

(2) 设计调度算法,为每个作业分配一台可用机器;

(3) 给出分配方案。

3) 设计思想

假设有七个作业,所需时间分别为{2, 14, 4, 16, 6, 5, 3},有三台机器,编号分别为m1m2m3。这七个作业在三台机器上进行调度的情形如图9所示,阴影区代表作业的运行区间。作业4016时间被调度到机器1上运行,在这16个时间单位中,机器1完成了对作业4的处理;作业2014时间被调度到机器2上处理,之后机器21417时间处理作业7;在机器3上,作业506时间完成,作业6611时间完成,作业31115时间完成,作业11517时间完成。注意到作业i只能在一台机器上从si时刻到si +ti时间完成且任何机器在同一时刻仅能处理一个作业,因此最短调度长度为17

在上述处理中,采用了最长时间优先(LPT)的简单调度策略。在LPT算法中,作业按其所需时间的递减顺序排列,在分配一个作业时,将其分配给最先变为空闲的机器

下面设计完成LPT算法的存储结构。

· 为每个机器设计数据类型:

    struct  MachineNode

    {

int ID;    //机器号

int avail;  //机器可用时刻

    };

   · 为每个作业设计数据类型:

    struct  JobNode

    {

int ID;    //作业号

int time;   //处理时间

    };

LPT算法用伪代码描述如下:

1. 如果作业数n≤机器数m,则

   1.1 将作业i分配到机器i上;

   1.2 最短调度长度等于n个作业中处理时间最大值;

2. 否则,重复执行以下操作,直到n个作业都被分配:

   2.1 n个作业按处理时间建成一个大根堆H1

   2.2 m个机器按可用时刻建立一个小根堆H2

   2.3 将堆H1的堆顶作业分配给堆H2的堆顶机器;

   2.4 H2的堆顶机器加上H1的堆顶作业的处理时间重新插入h2中;

   2.5 将堆H1的堆顶元素删除;

3. H2的堆顶元素就是最短调度时间;

 

 

 

#include<iostream>
#define N 10   //限定机器数和作业数不超过N个,这里N取10
using namespace std;
//******************************************
struct MachineNode
{
 int ID;     //机器号
 int avail; //机器可用时间
};
struct JobNode
{
 int ID;     //作业号
 int time; //处理时间
};

 


//*******************************************
//建立大根堆

void SiftD(JobNode r[],int k,int m)
{
 int i,j;
 i=k;
 j=2*i;
 while(j<=m)
 {
  if(j<m&&r[j].time<r[j+1].time)j++;
  if(r[i].time>r[j].time)break;
  else
  {
   int temp1,temp2;
   temp1=r[i].time;
   r[i].time=r[j].time;
   r[j].time=temp1;
   temp2=r[i].ID;
   r[i].ID=r[j].ID;
   r[j].ID=temp2;
  }
 }
}
void HeapSortD(JobNode r[],int n) 
{
 for(int i=n/2;i>=1;i--)
  SiftD(r,i,n);
}
//*********************************************

//*********************************************
//建立小根堆
void SiftX(MachineNode r[],int k,int m)
{
 int i,j;
 i=k;
 j=2*i;
 while(j<=m)
 {
  if(j<m&&r[j].avail>r[j+1].avail)j++;
  if(r[i].avail<r[j].avail)break;
  else
  {
   int temp1,temp2;
   temp1=r[i].avail;
   r[i].avail=r[j].avail;
   r[j].avail=temp1;
   temp2=r[i].ID;
   r[i].ID=r[j].ID;
   r[j].ID=temp2;
  }
 }
}
void HeapSortX(MachineNode r[],int n)
{
 for(int i=n/2;i>=1;i--)
  SiftX(r,i,n);
}

//**********************************************

void assign(MachineNode M[],JobNode J[],int m,int j)  //完成任务分配
{
 if(m>=j)   //如果机器数m大于或等于作业数j
 {
  cout<<"一台机器完成一个作业,最大工作时间为:";
  HeapSortD(J,j);   //以各作业所需时间建立大根堆,堆顶元素即为最大耗时的作业
   cout<<J[1].time<<endl;  //最大工作时间即为最大耗时的作业的所需时间
 }
 else  //如果机器数m小于作业数j
 {
  for(int i=1;i<=m;i++) //先为每台机器分配一个作业,先把所需时间最大的m个作业分配给m台机器。
  {
  HeapSortD(J,j);  //建立大根堆求堆顶元素确定其中耗时最大的作业
  M[i].avail=J[1].time;  //机器i的处理时间即为作业的所需时间
  cout<<"机器"<<M[i].ID<<"完成作业"<<J[1].ID<<endl;
  for(int k=1;k<j;k++)  //减去已分配的作业
   J[k]=J[k+1];
  j=j-1;
  }
  for(int q=j;j>=1;q--) //把剩余的j-m个作业分配下去(j=j-m)
  {
  HeapSortX(M,m);  //将m机器个机器按可用时建立小根堆
  HeapSortD(J,j);  //将j个作业按处理时间建立大根堆
  cout<<"机器"<<M[1].ID<<"完成作业"<<J[1].ID<<endl;  //将大根堆的堆顶作业分配给小根堆的堆顶机器
  M[1].avail+=J[1].time; //将小根堆的堆顶机器加上大根堆的堆顶作业的处理时间,重新插入小根堆(循环执行HeapSortX(M,m)时完成)
  for(int k=1;k<j;k++)  //减去已分配的作业
   J[k]=J[k+1];
  j=j-1;
  }
 cout<<"最短调度时间为:"<<M[1].avail<<endl;  //小根堆的堆顶元素就是最短调用时间
 }
}
void main()
{
 int j=0;    //作业个数
 int m=0; //机器个数
 int i;
 MachineNode M[N];     //机器的结构体数组
 JobNode J[N];         //作业的结构体数组
 cout<<"请输入作业个数:";
 cin>>j;
 cout<<"请输入每个作业需要的处理时间:"<<endl;
 for(i=1;i<=j;i++)            
 {
  J[i].ID=i;                     //为每个作业确定序号
  cout<<"第"<<i<<"个作业:" ;
  cin>>J[i].time;                //输入每个作业的用时
 }
 cout<<"请输入机器的个数:";
 cin>>m;
 for(i=1;i<=m;i++)
  M[i].ID=i;      //为每台机器确定序号
 assign(M,J,m,j);                    //调用完成分配任务的函数
}