#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)。