数据结构、算法与应用 12.6.2 机器调度(第十二章 315页)

#ifndef JOBNODE_H
#define JOBNODE_H

struct jobNode
{
	int id;          // 作业号
	int time;        // 处理时间

	jobNode() = default;
	jobNode(int cheId, int theTime)
		{id = cheId; time = theTime;}

	operator int() const
		{return time;}
};

#endif // !JOBNODE_H
#ifndef MACHINENODE_H
#define MACHINENODE_H
#include <iostream>	

struct machineNode
{
	int id;     // 机器号
	int avail;  // 机器可用时间

	machineNode() = default;
	machineNode(int theId, int theAvail)
		{id = theId; avail = theAvail;}

	operator int() const
		{return avail;}
};

#endif // !MACHINENODE_H
// 更改数组的长度

#ifndef changeLength1D_
#define changeLength1D_

#include "myExceptions.h"

using namespace std;

template<class T>
void changeLength1D(T*& a, int oldLength, int newLength)
{
   if (newLength < 0)
      throw illegalParameterValue("new length must be >= 0");

   T* temp = new T[newLength];              // 新阵列
   int number = min(oldLength, newLength);  // 要复制的编号
   copy(a, a + number, temp);
   delete [] a;                             // 释放旧内存
   a = temp;
}

#endif
#ifndef MINHEAP_H
#define MINHEAP_H

#include "changeLength1D.h"
#include "minPriorityQueue.h"
#include "myExceptions.h"
#include <sstream>
#include <algorithm>

using namespace std;

template<class T>
class minHeap : public minPriorityQueue<T>
{
   public:
      minHeap(int initialCapacity = 10);
      ~minHeap() {delete [] heap;}
      bool empty() const {return heapSize == 0;}
      int size() const
          {return heapSize;}
      const T& top()
         {// 返回最大元素
            if (heapSize == 0)
               throw queueEmpty();
            return heap[1];
         }
      void pop();
      void push(const T&);
      void initialize(T *, int);
      void deactivateArray()
         {heap = NULL; arrayLength = heapSize = 0;}
      void output(ostream& out) const;
   private:
      int heapSize;       // 队列中的元素数
      int arrayLength;    // 队列容量 + 1
      T *heap;            // 元素数组
};

template<class T>
minHeap<T>::minHeap(int initialCapacity)
{// 构造函数
   if (initialCapacity < 1)
   {ostringstream s;
    s << "Initial capacity = " << initialCapacity << " Must be > 0";
    throw illegalParameterValue(s.str());
   }
   arrayLength = initialCapacity + 1;
   heap = new T[arrayLength];
   heapSize = 0;
}

template<typename T>
void minHeap<T>::push(const T& theElement)
{// 把元素 theElement 加入堆

    // 必要时增加数组长度
    if (heapSize == arrayLength - 1)
    {// 长度 * 2
        changeLength1D(heap, arrayLength, 2 * arrayLength);
        arrayLength *= 2;
    }
    
    // 为元素 theElement 寻找插入位置
    // currentNode 从新叶子向上移动
    int currentNode = ++heapSize;
    while (currentNode != 1 && heap[currentNode / 2] > theElement)
    {
        // 不能把元素 theElement 插入在 heap[currentNode]
        heap[currentNode] = heap[currentNode / 2];           // 把元素向下移动
        currentNode /= 2;                                    // currentNoed 移向双亲
    }

    heap[currentNode] = theElement;
}

template<typename T>
void minHeap<T>::pop()
{// 删除最大元素
    // 如果堆为空,抛出异常
    if (heapSize == 0)     // 堆空
        throw queueEmpty();

    // 删除最大元素
    heap[1].~T();

    // 删除最后一个元素,然后重建堆
    T lastElement = heap[heapSize--];

    // 从根开始,为最后一个元素寻找位置
    int currentNode = 1,
        child = 2;                         // currentNode 的孩子
    while (child <= heapSize)
    {
        // heap[child] 应该是 currentNode 的更大的孩子
        if (child < heapSize && heap[child] > heap[child + 1])
            child++;

        // 可以把 lastElement 放在 heap[currentNode] 吗?
        if (lastElement <= heap[child]) 
            break;                          // 可以

        // 不可以
        heap[currentNode] = heap[child];      // 把孩子 child 向上移动
        currentNode = child;                  // 向下移动一层寻找位置
        child *= 2;
    }
    heap[currentNode] = lastElement;
}

template<typename T>
void minHeap<T>::initialize(T *theHeap, int theSize)
{// 在数组 theHeap[1:theSize] 中建大根堆
    delete [] heap;
    heap = theHeap;
    heapSize = theSize;

    // 堆化
    for (int root = heapSize / 2; root >= 1; root--)
    {
        T rootElement = heap[root];

        // 为元素 rootElement 寻找位置
        int child = 2 * root;     // 孩子 child 的双亲是元素 rootElement 的位置 
        while (child <= heapSize)
        {
            // heap[child] 应该是兄弟中较大者
            if (child < heapSize && heap[child] > heap[child + 1]) 
                child++;

            // 可以把元素 rootElement 放在 heap[child / 2] 吗
            if (rootElement <= heap[child])
                break;

            // 不可以
            heap[child / 2] = heap[child];          // 把孩子向上移
            child *= 2;                             // 移到下一层
        }
        heap[child / 2] = rootElement;
    }
}

template<class T>
void minHeap<T>::output(ostream& out) const
{// 将列表放入流中并输出
   copy(heap + 1, heap + heapSize + 1, ostream_iterator<T>(cout, "  "));
}

// 重载 <<
template <class T>
ostream& operator<<(ostream& out, const minHeap<T>& x)
   {x.output(out); return out;}

#endif // !MAXHEAP_H
// 程序 12-8 用堆排序给数组 a[1:n] 排序
template<typename T>
void heapSort(T a[], int n)
{// 使用堆排序方法给数组 a[1:n] 排序
    // 在数组上建立大根堆
    minHeap<T> heap(1);
    heap.initialize(a, n);

    // 逐个从大根堆中提取元素
    for (int i = n - 1; i >= 1; i--)
    {
        T x = heap.top();
        heap.pop();
        a[i + 1] = x;
    }

    // 从堆的析构函数中保存数组 a
    heap.deactivateArray();
        for (int i = 0; i < n; i++)
        cout << a[i] << endl;
}
// 程序 12-9 基于 a[1:n] 的 m 台机器的 LPT 调度
void makeSchedule(jobNode a[], int n, int m)
{// 输出一个基于 n 个作业 a[1:n] 的 m 台机器的 LPT 调度
    if (n <= m)
    {
        cout << "在不同的机器上安排每个作业." << endl;
        return;
    }

    heapSort(a, n);         // 按递增顺序排序
    // 初始化 m 台机器,建立小根堆
    minHeap<machineNode> machineHeap(m);
    for (int i = 1; i <= m; i++)
    {
        machineHeap.push(machineNode(i, 0));     // 1, 0          2, 0           3, 0
    }

    //生成调度计划
    for (int i = n; i >= 1; i--)
    {// 把作业 i 安排在第一台空闲的机器
        machineNode x = machineHeap.top();
        machineHeap.pop();
        cout << "安排工作 " << a[i].id << " 在机器上 "<< x.id << " 从 " << x.avail << " 到 " << (x.avail + a[i].time) << endl;

        x.avail += a[i].time;      // 这台机器新的空闲时间
        machineHeap.push(x);
    }
}
// abstract class min priority queue
// all methods are pure virtual functions

#ifndef minPriorityQueue_
#define minPriorityQueue_

using namespace std;

template<class T>
class minPriorityQueue 
{
   public:
      virtual ~minPriorityQueue() {}
      virtual bool empty() const = 0;
                  // return true iff queue is empty
      virtual int size() const = 0;
                  // return number of elements in queue
      virtual const T& top() = 0;
                  // return reference to the min element
      virtual void pop() = 0;
                  // remove the top element
      virtual void push(const T& theElement) = 0;
                  // add theElement to the queue
};
#endif

// exception classes for various error types

#ifndef myExceptions_
#define myExceptions_
#include <string>

using namespace std;

// illegal parameter value
class illegalParameterValue 
{
   public:
      illegalParameterValue(string theMessage = "Illegal parameter value")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// illegal input data
class illegalInputData 
{
   public:
      illegalInputData(string theMessage = "Illegal data input")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// illegal index
class illegalIndex 
{
   public:
      illegalIndex(string theMessage = "Illegal index")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// matrix index out of bounds
class matrixIndexOutOfBounds 
{
   public:
      matrixIndexOutOfBounds
            (string theMessage = "Matrix index out of bounds")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// matrix size mismatch
class matrixSizeMismatch 
{
   public:
      matrixSizeMismatch(string theMessage = 
                   "The size of the two matrics doesn't match")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// stack is empty
class stackEmpty
{
   public:
      stackEmpty(string theMessage = 
                   "Invalid operation on empty stack")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// queue is empty
class queueEmpty
{
   public:
      queueEmpty(string theMessage = 
                   "Invalid operation on empty queue")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// hash table is full
class hashTableFull
{
   public:
      hashTableFull(string theMessage = 
                   "The hash table is full")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// edge weight undefined
class undefinedEdgeWeight
{
   public:
      undefinedEdgeWeight(string theMessage = 
                   "No edge weights defined")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// method undefined
class undefinedMethod
{
   public:
      undefinedMethod(string theMessage = 
                   "This method is undefined")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};
#endif

函数 makeSchedule 的复杂性分析:

    当 n <= m 时,makeSchedule 函数所需时间为 Θ(1)。当 n > m 时,堆排序时间为 Ο(nlogn)。

堆初始化时间是 Ο(m),因为尽管执行了 m 次插入,但所有元素的值相同,因此每次插入的时间都为Θ(1),每次 pop 和 push 的时间是 Ο(logm)。因此第二个 for 循环时间为 Ο(nlogm)。于是,对 n > m,makeSchedule 函数的总时间为 Ο(nlogn + nlogm) = Ο(nlogn)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值