代码改变世界

《算法导论》第6章 堆排序 (2)优先级队列

2012-02-17 22:25  htc开发  阅读(118)  评论(0编辑  收藏  举报



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;
}