优先级队列
提起优先级队列,首先想到了操作系统中的作业调度算法的相关应用,还有就是解决 Top n (一个集合中最大或最小的n的元素)之类的问题。
操作系统中的作业调度有短作业优先(SJF)、先来先服务(FCFS)、时间片轮转法、优先级法等。
其中,优先级法可以近似看成是利用了优先级队列,根据作业的优先级来从作业队列中选择下一个将要执行的作业。而Top n之类的问题也是这样。优先级队列可以用 * 堆 *这一数据结构来描述并解决,这样的编码和计算效率都很高。
优先级队列操作一个初始为空的元素集合称为S。
- insert——在集合中插入一个新元素
- extractmin——删除集合中的最小元素(或最大元素)
优先级队列的堆实现使用了具有堆性质的数组x[1…n]表示n元集合。x在C或C++中声明为x[maxsize + 1]从x[1]开始使用,通过复制n = 0 将集合初始化为空,每插入一个新元素时,n就加1,并将元素放在x[n]处。
下面是插入元素的伪代码:
void insert(t)
if n >= maxsize
error
n++
x[n] = t
Heapify(x)//调整数组x,使之具有最小堆的性质
extractmin查找并删除集合中的最小元素,然后使集合重新具有堆的性质。由于开始初始化成了一个最小堆,所以最小元素位于x[1]处,集合中剩下的n-1个元素位于x[2…n-1]中。首先,将x[n]移到x[1]处,将n减1;然后将x[1…n-1]重新调整为具有最小堆性质的数组即可。
下面是extractmin函数伪代码:
int extractmin()
if n < 1
error
t = x[1]
x[1] = x[n]
n--
Heapify(x)//调整数组x,使之重新具有最小堆的性质
最后是优先级队列的完整C++实现:
template <class T>
class PriorityQueue{
private:
int n, maxsize;
T *x;
void swap(int i, int j)
{
T temp = x[i];
x[i] = x[j];
x[j] = temp;
}
public:
PriorityQueue(int m)//优先级队列构造函数
{
maxsize = m;
x = new T[maxsize + 1];
n = 0;
}
~PriorityQueue(){}//析构函数
void insert(T t)
{
int i, p;
x[++n] = t;
for(i = n; i > 1 && x[p = i / 2] > x[i]; i =p)
swap(p, i);
}
T extractmin()
{
int x, c;
T temp = x[1];
x[1] = x[n--];
for(i = 1; (c = 2 * i) <= n; i = c)
{
if(c + 1 <= n && x[c + 1] < x[c])//选取子结点中较小的一个
c++;
if(x[i] < x[c])
break;
swap(c, i);
}
return temp;
}