6.5 优先级队列
在实际中堆的一个很常见的应用:用来实现高效的优先级队列。
优先级队列分为最大优先级队列和最小优先级队列。
最大优先级队列的一个应用是在一台分时计算机上进行作业调度。
需要在堆中的每个元素里存储对应对象的柄(handle)。
#include <stdio.h>
#define PARENT(i) ((i) / 2)
int heap_maximum(int A[])
{
return A[1];
}
// HEAP-MAXIMUM与HEAPSORT中的for循环体一样。
// 将最后一个元素挪到根位置,堆大小减一,保持堆性质。
int heap_extract_max(int A[], int *heapsize)
{
int max = A[1];
A[1] = A[*heapsize];
*heapsize -= 1;
max_heapify(A, *heapsize, 1);
return max;
}
// HEAP-INCREASE-KEY与MAX-HEAPIFY的区别:
// HEAP-INCREASE-KEY是当前结点的值增大了,因此要向上将父结点与该结点交换。
// MAX-HEAPIFY是保持当前结点为根的树是对,因此将当前结点与两个子结点比较,
// 向下逐层恢复堆的性质。
void heap_increase_key(int A[], int i, int key)
{
A[i] = key;
while (i > 1 && A[PARENT(i)] < A[i]) {
exchange(A, i, PARENT(i));
i = PARENT(i);
}
}
// 相当于将尾部元素从无穷小增大到key。
void max_heap_insert(int A[], int *heapsize, int key)
{
*heapsize += 1;
heap_increase_key(A, *heapsize, key);
}
//
习题6.5-7 需要注意的是尾部元素挪到删除位置后,有两种情况:
// 若比父结点小,则max_heapify,向下保持堆性质;
// 若比父结点小,则heap_increase_key向上。
// heap_delete(A, heapsize, 1)相当于heap_extract_max。
int heap_delete(int A[], int *heapsize, int i)
{
int key = A[i];
int last = A[*heapsize];
*heapsize -= 1;
if (last <= A[PARENT(i)]) {
A[i] = last;
max_heapify(A, *heapsize, i);
}
else {
heap_increase_key(A, i, last);
}
return key;
}
情况一:heap_delete(A, heapsize, 1)删除14,则9被挪到14的位置,
调用max_heapify(A, heapsize, 1)向下保持堆性质。
14
/ \
8 10
/ \ / \
4 7 9
情况二:heap_delete(A, heapsize, 4)删除4,则9被挪到4的位置,
调用heap_increase_key(A, 4, 9)。
14
/ \
8 10
/ \ / \
4
7 9
// 测试数据
int main(void)
{
int A[20] = { 0, 16, 4, 10, 14, 7, 9, 3, 2, 8, 1 };
int heapsize = 10;
build_max_heap(A, heapsize);
print(A, heapsize);
heap_extract_max(A, &heapsize);
print(A, heapsize);
heap_delete(A, &heapsize, 1);
print(A, heapsize);
return 1;
}